Create Generic Delegate for Class

Swift delegate for a generic class

It is hard to know what the best solution is to your problem without having more information, but one possible solution is to change your protocol declaration to this:

protocol MyClassDelegate: class {
func valueChanged<T>(genericClass: MyClass<T>)
}

That removes the need for a typealias in the protocol and should resolve the error messages that you've been getting.

Part of the reason why I'm not sure if this is the best solution for you is because I don't know how or where the valueChanged function is called, and so I don't know if it is practical to add a generic parameter to that function. If this solution doesn't work, post a comment.

Delegate for generic class and method with generic return type

The issue is here:

_myHandler = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), null, createMethod);

The second parameter of the overload of .CreateDelegate you're using takes an instance of the type to which the method belongs.

You should either make your method static, or create an instance of genericType:

var instance = Activator.CreateInstance(genericType);
_myHandler = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), instance, createMethod);

Creating a generic delegate using reflection

You should do exactly what the answer in the linked post did.

First, create a generic method that does the thing:

public static void Perform<T>(BsonClassMap<T> cm) {
cm.AutoMap();
cm.SetIsRootClass(true);
}

Then, get the method info of Perform:

var performMethodInfo = typeof(YourType).GetMethod("Perform").MakeGenericMethod(entityType);

Create a Type representing BsonClassMap<T> and create a Type representing Action out of it:

var typeOfBsonClassMap = typeof(BsonClassMap<>).MakeGenericType(entityType);
var typeOfAction = typeof(Action<>).MakeGenericType(typeOfBsonClassMap);

Now use Delegate.CreateDelegate:

var del = Delegate.CreateDelegate(typeOfAction, performMethodInfo);

And then you can pass it into the method:

genericMethod.Invoke(null, new object[] { del });

How can I call a generic delegate?

You should create an instance of the constructed delegate type Handler<Something>, rather than the unbound Handler<>. Basically, you should call MakeGenericType on typeof(Handler<>), just like you did on the two methods. You would also need to pass this to CreateDelegate, as methodApplicationGeneric is not a static method.

var delegateApplication = Delegate.CreateDelegate(
typeof(Library.Handler<>).MakeGenericType(type),
this,
methodApplicationGeneric
);

Set a generic class as a delegate in swift

When my XMLUtil class is a generic class

But Objective-C knows nothing of generic classes. So there is no way to show your XMLUtil class to Objective-C. Thus, it cannot serve as NSXMLParser's delegate; NSXMLParser is an Objective-C class and cannot see your XMLUtil class if it is generic.

One easy way to see this is to try to mark your XMLUtil class as @objc. You will fail; the compiler will stop you. There is no way to show this class to Objective-C.

creating a class that holds generic delegates

The question is a little confusing, so this may not be an answer, but it's too long for a comment! I think what you want to do is use Action(Of T) as the type for Container.Property1 and Container.Property2.

Something like this (this will run in LINQPad using Language: VB Program):

Sub Main

Dim c1 = New Container(Of String, String)()
c1.Property1 = AddressOf Method1
c1.Property2 = AddressOf Method1
Method3(c1)

Dim c2 = New Container(Of String, Integer)()
c2.Property1 = AddressOf Method1
c2.Property2 = AddressOf Method2
Method3(c2)

End Sub

Public Sub Method1(x As String)
Console.WriteLine("Method1: {0}", x)
End Sub

Public Sub Method2(x As Integer)
Console.WriteLine("Method2: {0}", x)
End Sub

Public Sub Method3(Of T1, T2)(container as Container(Of T1, T2))
Console.WriteLine("Method3 got {0}, {1}", GetType(T1), GetType(T2))
' Not sure how you would actually call the delegates
If GetType(T1) = GetType(String) Then
container.Property1.DynamicInvoke("Hello")
ElseIf GetType(T1) = GetType(Integer) Then
container.Property1.DynamicInvoke(123)
End If
If GetType(T2) = GetType(String) Then
container.Property2.DynamicInvoke("World")
ElseIf GetType(T2) = GetType(Integer) Then
container.Property2.DynamicInvoke(456)
End If
End Sub

Public Class Container(Of T1, T2)
Public Property Property1 As Action(Of T1)
Public Property Property2 As Action(Of T2)
End Class

This produces the following results:

Method3 got System.String, System.String
Method1: Hello
Method1: World
Method3 got System.String, System.Int32
Method1: Hello
Method2: 456

Generic Delegate C#

You're overcomplicating things.

public static class Cache
{
private static List<Dog> _dogs = new List<Dog>();
private static List<Cat> _cats = new List<Cat>();

public static TAnimal GetCachedObj<TAnimal>() where T: Animal
{
if(TAnimal == typeof(Dog))
return (TAnimal) _dogs.First();
else if (TAnimal == typeof(Cat))
return (TAnimal) _cats.First();
else throw new InvalidOperationException("Invalid generic type argument");
}
}

But your whole design has a flaw: it breaks the Liskov Substitution Principle.

The LSP states that if T (for example, Cat) is a subtype of Animal, then any instance of Animal can be replaced with T without any surprising effects.

Let me ellaborate. Say that you decide to create a new animal, a Giraffe. Now, if you call GetCachedObj<Giraffe>, you'll get an exception! The code does not work for any subtype of Animal, the LSP does not hold!

Instead you should make the cache class generic, and use a cache instance for every kind of animal

public class Cache<T> where T: Animal
{
private static List<T> _animals = new List<T>();

public T GetCachedObj()
{
return _animals.First();
}
}

var dogsCache = new Cache<Dog>();
Dog dog = dogsCache.GetCachedObj();

var catsCache = new Cache<Cat>();
Cat cat = catsCache.GetCachedObj();

This will always work for any kind of animal.

Note: I believe Cache shouldn't be static. Instead, you can use the Singleton pattern to have one single cache instance across the application (per animal type), or use Dependency Injection (with a framework such as Castle Windsor) to inject a cache into every client.


old answer

You either bind the method's generic type argument to a specific type at declaration-time (as @Sean mentioned), or you make the enclosing type generic as well.

public class MyClass<T>
{
public FirstDelegate<T> Method(){...}
}

You can also leave T unbound (without making the enclosing type generic), but you'll have to declare T after the method name, like so:

public FirstDelegate<T> Method<T>(){...}

Either way, at some point in time, T will be bound to a specific type. In this case, T will be bound when you create an instance of MyClass (i.e., new MyClass<int>), like you would do with a List<T>.

Generic delegate instances

This cannot be done, since what you're asking is declaring a variable (magic) of an unclosed generics type.

One can work with unclosed generics but only at the type level, e.g.:

delegate T FactoryDelegate<T>(string name);

var magicType = typeof (FactoryDelegate<>);

and then "close" the type at a later point:

var stringMagic = magicType.MakeGenericType(typeof(string));

Update: that said, here's a sample on how you can use the above technique to also work with unclosed method "types". Still not as elegant as it would be if we could assign unclosed types though..:

    public class UnclosedMethod
{
private readonly MethodInfo _method;

public UnclosedMethod(Type type, string method)
{
_method = type.GetMethod(method);
}

public T Invoke<T>(string name)
{
var fact = _method.MakeGenericMethod(typeof(T));
return (T)fact.Invoke(this, new object[] { name });
}
}

And then in code do this:

var magic = new UnclosedMethod(typeof(Foo), "Factory");
var x = magic.Invoke<string>("bar");

How create a generic Func delegate

Only classes and methods can be generic in and of themselves. A field that uses generic parameters must be within a generic class context:

public class Test<T>
{
public static T F(T arg)
{
return arg;
}

public Func<T, T> FuncF = F;
}

Or if the type parameter for F should not be connected to FuncF, then just use a different name for one of the parameters:

public class Test<T>
{
public static U F<U>(U arg)
{
return arg;
}

public Func<T, T> FuncF = F;
}


Related Topics



Leave a reply



Submit