[英]C# Cast object to generic interface with Type parameter
我想将对象转换为通用自定义接口。
这是我的界面:
public interface IContainer<T>
{
IEnumerable<T> SaveToCache(IEnumerable<T> models);
}
public class Container<T>
{
IEnumerable<T> SaveToCache(IEnumerable<T> models);
}
我在Serviceclass中使用此接口:
public class Manager()
{
public Manager()
{
address = new Container<Address>(this);
// more containers are constructed here...
}
private static Container<Address> address;
public static Container<Address> Address => address;
// here are more properties of Type Container<T>
}
现在我想动态调用SaveToCacheAsync
方法,如下所示:
private void SaveItems(IEnumerable<object> items, string typeName)
{
object container = typeof(Manager)
.GetRuntimeProperty(typeName).GetValue(null, null);
var t = Type.GetType($"MyNameSpace.Models.{typeName}");
// variant A - doesn't work, but makes clear what I want to do
(container as IContainer<t>).SaveToCache(items);
// variant B - doesn't work either
var saveMethod = container.GetType()
.GetRuntimeMethod("SaveToCache", new Type[] { Type.GetType($"System.Collections.Generic.List`1[{t.FullName}]") })
.MakeGenericMethod(new Type[] { t });
saveMethod.Invoke(container, new object[] { });
}
该项目是PCL,因此我使用了GetRuntimeMethods
。
您的第二个版本不起作用,因为该方法本身不是通用的,类是,并且您拥有的Type
实例已经是实例化的泛型类型,因为您从它获取它形成一个对象实例。 虽然这个版本有效,但它并不理想,因为它涉及使用反射来调用方法,这种方法很慢并且通常看起来像代码味道
var saveMethod = container.GetType()
.GetRuntimeMethod("SaveToCache", new Type[] { typeof(IEnumerable<>).MakeGenericType(t) })
.Invoke (container, new object[] { items });
更好的方法是拥有一个非通用版本的接口(很像IEnumerable<T>
和IEnumerable
)
public interface IContainer
{
IEnumerable SaveToCache(IEnumerable models);
}
public interface IContainer<T> : IContainer
{
IEnumerable<T> SaveToCache(IEnumerable<T> models);
}
您的类可以显式实现IContainer
以避免调用非泛型方法,并仅在SaveItems
方法的上下文中使用它
public class Container<T> : IContainer<T>
{
public IEnumerable<T> SaveToCache(IEnumerable<T> models)
{
return models;
}
IEnumerable IContainer.SaveToCache(IEnumerable models)
{
}
}
var container = new Container<string>();
container.SaveToCache(new string[] { "" }); // The generic method is avaiable if we have an referecne to the class
container.SaveToCache(new int[] { 0 });// And this will be a compile time error as expected
IContainer icontainer = container;
icontainer.SaveToCache(new string[] { "" }); // The non genric method will be called
icontainer.SaveToCache(new int[] { 0 });// And this will be a runtime time error
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.