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
Swift - Segue from Button Inside a Cell
How to Know Where Optional Chaining Is Breaking
Swiftui Sheet Not Updating Variable
Calculate Time Difference in Swift 4
Updating a @Published Variable Based on Changes in an Observed Variable
Why It Is Called the Memberwise Initialiser
Avplayer Can't Resume After Paused + Some Waiting
Instagram Explorer Searchbar and Tableview
Unsafemutablepointer<Void> to Concrete Object Type
Accessibility (Voice Over) with Sprite Kit
Ios/Tvos Playground Fails with "Unable to Find Execution Service for Selected Run Destination"
Nsdateformatter Detect 24-Hour Clock in Os X and iOS