问题
I have a generic method declared as follow :
public void Duplicate<EntityType>() { ... }
So, generally to use it I simply need to do say :
myObject.Duplicate<int>()
But here, what I'd like to do is pass the type by a variable, but it doesn't work, here is how I try to do this :
Type myType = anObject.GetType();
myObject.Duplicate<myType>();
If someone can help me ?
Thank in advance.
回答1:
You have to use reflection, basically:
MethodInfo method = typeof(...).GetMethod("Duplicate");
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(myObject, null);
回答2:
Where you have the type as a variable you don't really have a good candidate for generic methods, especially as your method returns nothing.
You would be better off with:
public void Duplicate(Type entityType) { ... }
Then your code becomes:
Type myType = anObject.GetType();
myObject.Duplicate(myType);
You can use Jon Skeet's (correct) answer to call your method by reflection, but I can't see what you gain by this method being generic.
The purpose of generics is to preserve the type - so that you don't have to box/unbox value types and so on.
However your duplicate method has no return (it's a void) and no input parameters. Essentially the only input is the type-parameter. This means that somewhere inside your generic method you're probably doing something like:
public void Duplicate<EntityType>()
{
...
Type inputType = typeof(EntityType);
...
}
In that case you're not gaining anything by EntityType being a generic type-parameter rather than a regular input parameter, and you're adding the need for awkward and slow reflection when you don't know the input at compile time.
回答3:
You could use a standard method taking a Type as an argument:
myobject.Duplicate(myType);
or you can try with reflection, something like:
System.Reflection.MethodInfo mi = typeof(TypeOfMyObject).GetMethod("Duplicate<>");
MethodInfo constructedMethodInfo = mi.MakeGenericMethod(new type[] {myType});
constructedMethodInfo.Invoke(myObject, new object[] {});
回答4:
It's not quite clear of the exact function of Duplicate(), but the following example works when your type you want to pass in to Duplicate() is a class or an int.
Essentially, don't pass in a type, pass in an example object. This test method illustrates the call (two tests in one method)
[TestMethod]
public void TestMethod1()
{
var myObject = new AnObject { AString = "someString" };
var myOtherObject = new AnotherObject();
var newObject = myObject.Duplicate(myOtherObject);
Assert.IsTrue(newObject.AString=="someString");
var newObject2 = myObject.Duplicate(1);
Assert.IsTrue(newObject2 is Int32);
}
The Duplicate() method has a type parameter linked to the example object, but does not need to be called with the type given as a parameter, it infers it from the example object.
Here is the class with a Duplicate() method:
public class AnObject
{
public string AString { get; set; }
public T Duplicate<T>(T exampleObject)
where T: new()
{
var newInstance = (T)Activator.CreateInstance<T>();
// do some stuff here to newInstance based on this AnObject
if (typeof (T) == typeof (AnotherObject))
{
var another = newInstance as AnotherObject;
if(another!=null)
another.AString = this.AString;
}
return newInstance;
}
}
To complete the picture, this is the AnotherObject class.
public class AnotherObject
{
public string AString { get; set; }
}
This code may have some problems inside the Duplicate() method when the type passed in is a value type like int. It depends on what you want Duplicate() to do with the int (you may have to be pass it in as a nullable int).
It works well for reference types (classes).
来源:https://stackoverflow.com/questions/5961816/c-sharp-generic-method-and-dynamic-type-problem