我想将对象转换为通用自定义接口。
这是我的界面:
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
。
答案 0 :(得分:0)
你的第二个版本不起作用,因为该方法本身不是通用的,类是,并且你拥有的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