C# 我如何使用反射传递每个列表的;“我的类型”;到约束为T:MyType的泛型方法?
如何使用反射将每个“MyTypes”列表传递给约束为T:MyDataObject的泛型方法C# 我如何使用反射传递每个列表的;“我的类型”;到约束为T:MyType的泛型方法?,c#,generics,reflection,C#,Generics,Reflection,如何使用反射将每个“MyTypes”列表传递给约束为T:MyDataObject的泛型方法 public interface IAllMyTypes { List<FirstType> MyType1 { get; set; } List<SecondType> MyType2 { get; set; } List<ThirdType> MyType3 { get; set; } } 我无法将数据传递到具有此签名的方法: void D
public interface IAllMyTypes
{
List<FirstType> MyType1 { get; set; }
List<SecondType> MyType2 { get; set; }
List<ThirdType> MyType3 { get; set; }
}
我无法将数据传递到具有此签名的方法:
void DoSomething<T>(IEnumerable<T> enumerable) where T : MyDataObject;
如果我直接提供如下属性,DoSomething(..)中的所有代码都能正常工作:
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
DoSomething(allMyTypes.MyType1);
DoSomething(allMyTypes.MyType2);
DoSomething(allMyTypes.MyType3);
}
我正在努力寻找一种情况,在这种情况下,您需要按照您的方式构建数据,而不会使事情过于复杂。如果你发现了一个合法的案例,请发表评论,我会更新我的答案以反映你的需求 您可以从基类开始,将其抽象化,并在其中放入一个抽象方法
DoSomething
public abstract class MyDataObject{
public string SomeSharedProperty{get;set;}
protected abstract DoSomething();
}
public class FirstType: MyDataObject{
protected override DoSomething(){
Console.WriteLine(SomeSharedProperty);
}
}
public class Consumer{
public void DoSomethingWithAllMyTypes(List<MyDataObject> source)
{
source.ForEach(x=>x.DoSomething());
}
}
公共抽象类MyDataObject{
公共字符串SomeSharedProperty{get;set;}
受保护的抽象剂量学();
}
公共类FirstType:MyDataObject{
受保护的覆盖剂量计(){
Console.WriteLine(某些共享属性);
}
}
公共类消费者{
public void DoSomethingWithAllMyTypes(列表源)
{
source.ForEach(x=>x.DoSomething());
}
}
如果要使用反射,也可以使用反射调用助手方法:
您必须获得泛型方法的MethodInfo
,并创建泛型方法反射句柄以实际调用该方法。在这种情况下,需要在运行时获取泛型方法的类型T
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
var method = this.GetType().GetMethod("DoSomething", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo propertyInfo in allMyTypes.GetType().GetProperties())
{
var x = propertyInfo.GetValue(allMyTypes, null);
if(x==null) throw new Exception("still wrong");
// obtain the type from the property - other techniques can be used here.
var genericMethod = method.MakeGenericMethod(new[] {propertyInfo.PropertyType.GetGenericArguments()[0]})
//execute the generic helper
genericMethod.Invoke(this, new[]{x});
}
}
public void DoSomething<T>(IList<T> list) where T : MyDataObject {
}
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
var method=this.GetType().GetMethod(“DoSomething”,BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
foreach(allMyTypes.GetType().GetProperties()中的PropertyInfo PropertyInfo)
{
var x=propertyInfo.GetValue(allMyTypes,null);
如果(x==null)抛出新异常(“仍然错误”);
//从属性获取类型-这里可以使用其他技术。
var genericMethod=method.MakeGenericMethod(新[]{propertyInfo.PropertyType.GetGenericArguments()[0]})
//执行泛型助手
Invoke(this,new[]{x});
}
}
公共void DoSomething(IList列表),其中T:MyDataObject{
}
您可以使用Linq方法调用Cast
将列表转换为正确的类型
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
foreach (PropertyInfo propertyInfo in allMyTypes.GetType().GetProperties())
{
var x = propertyInfo.GetValue(allMyTypes) as IEnumerable
if(x==null) throw new Exception("still wrong");
DoSomething(x.Cast<MyDataObject>());
}
}
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
foreach(allMyTypes.GetType().GetProperties()中的PropertyInfo PropertyInfo)
{
var x=propertyInfo.GetValue(allMyTypes)作为IEnumerable
如果(x==null)抛出新异常(“仍然错误”);
DoSomething(x.Cast());
}
}
<代码> > IIST < /COD>(非泛型)会很好。如果你做这些步骤的唯一原因是调用多个次数,那么考虑一个数据结构,如列表类型列表=新列表{Type(A),Type of(B),Type(C)};而不是你的我的类型。然后你可以迭代它,并更改DoSomething的函数签名。它应该是allMyTypes.GetType().GetProperties()
还是typeof(IAllMyTypes)。GetProperties()
将它放入并第一次使用!就是这样。非常感谢。我不确定这是否需要一个全新的问题,但我在其他地方用DoSomethingElse(IEnumerable list)方法做了类似的事情,我试图传递到前面的同一个DoSomething方法,但是,我得到了一个错误:“System.Collections.Generic.list1[MyDataObject]类型的对象”“无法转换为类型”System.Collections.Generic.IEnumerable
1[FirstType]”。我试图修改上面的例子,但显然我有点错误。这不起作用,因为DoSomething中的T类型是“MyDataObject”,而不是真正的类型,如FirstType、SecondType、,etc导致代码中的反射只能访问MyDataObject的成员。@user2565663不,这不是真的,反射不会在意,因为GetType将返回真的类型。我已经运行了这个示例,但实际情况并非如此。你能分享一些代码来证明你说的是真的吗?当我在DoSomething中时,T是一个MyDataObject,我不知道如何才能在它上键入并获得不同的类型。@user2565663 insideDoSomething(T value)
:typeof(T)
将返回MyDataObject,但是value。GetType()
将返回值的真正类型,无论您如何强制转换它。例如,尝试在变量x
中拥有一个类型为FirstType
的对象,然后调用DoSomething((MyDataObject)x)
@user2565663如果您使用的是反射,那么您真的不应该使用泛型,泛型实际上适用于基于非反射的方法,在这种方法中,您需要返回原始类型,或者在编译时需要绝对类型。如果您使DoSomething非泛型,接受类型为MyDataObject
的对象,并在值上使用GetType(在检查其非null之后),那么您的代码也可以正常工作
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
var method = this.GetType().GetMethod("DoSomething", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo propertyInfo in allMyTypes.GetType().GetProperties())
{
var x = propertyInfo.GetValue(allMyTypes, null);
if(x==null) throw new Exception("still wrong");
// obtain the type from the property - other techniques can be used here.
var genericMethod = method.MakeGenericMethod(new[] {propertyInfo.PropertyType.GetGenericArguments()[0]})
//execute the generic helper
genericMethod.Invoke(this, new[]{x});
}
}
public void DoSomething<T>(IList<T> list) where T : MyDataObject {
}
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
foreach (PropertyInfo propertyInfo in allMyTypes.GetType().GetProperties())
{
var x = propertyInfo.GetValue(allMyTypes) as IEnumerable
if(x==null) throw new Exception("still wrong");
DoSomething(x.Cast<MyDataObject>());
}
}