[英]C# Calling a Method on an Unknown Generic Type
我有一个具有通用静态函数“ GetManager”的基类“ ManagerBase”。有两个继承自ManagerBase的类(“ ManagerSomething1”和“ ManagerSomething2”)。每个类都有一个静态函数“ GetManager”,该函数返回继承的继承类型。 ManagerBase。如何在不知道类型的情况下调用GetManager?
public class ManagerBase
{
public static T GetManager<T>(int managerID, bool withUsers, System.Func<SqlDataReader, T> del) where T : ManagerBase
{
T manager = del(dr);
return manager;
}
}
public class ManagerSomething1 : ManagerBase
{
public static ManagerSomething1 GetManager<ManagerSomething1>(int managerID, bool withUsers)
{
return ManagerBase.GetManager<ManagerSomething1>(managerID, withUsers, dr => new ManagerSomething1(dr));
}
}
public class ManagerSomething2 : ManagerBase
{
public static ManagerSomething2 GetManager<ManagerSomething2>(int managerID, bool withUsers)
{
return ManagerBase.GetManager<ManagerSomething2>(managerID, withUsers, dr => new ManagerSomething2(dr));
}
}
public static class SessionSharedHelper<T> where T : ManagerBase
{
public static void InitializeSession(int managerID, bool withUsers)
{
SessionShared<T>.Manager = //I don't know how I can call ManagerBase.GetManager<T>(managerID, withUsers, ...);
}
}
您可以重构为以下内容:
public abstract class ManagerBase
{
public ManagerBase() { }
public abstract void Initialize(int managerID, bool withUsers);
}
public class ManagerSomething1 : ManagerBase
{
public ManagerSomething1()
{ }
public override void Initialize(int managerID, bool withUsers)
{
}
}
public class ManagerSomething2 : ManagerBase
{
public ManagerSomething2()
{
}
public override void Initialize(int managerID, bool withUsers)
{
throw new NotImplementedException();
}
}
public static class SessionSharedHelper<T> where T : ManagerBase, new()
{
public static void InitializeSession(int managerID, bool withUsers)
{
T manager = new T();
manager.Initialize(managerID, withUsers);
}
}
这样的事情可能会起作用:
MethodInfo method_info = typeof(T).GetMethod("GetManager",
System.Reflection.BindingFlags.Static | BindingFlags.Public);
SessionShared<T>.Manager =
(T)method_info.Invoke(null, new object[]{managerID, withUsers, ...});
我认为您正在尝试在要构造的类中实现某种工厂模式。
您可以采用两种方法:有一个单独的类,该类知道如何构造Manager1和Manager2,或者让基类知道如何构造其每个子级。 无论哪种方式,都需要对每个子类有所了解。 我认为没有一种反思的好方法。
我可能会在单独的工厂类中实现这样的事情。
public static T GetManager<T>(int managerID, bool withUsers) where T : ManagerBase
{
if (typeof(T) == typeof(Manager1))
{
return new Manager1(managerID, withUsers) as T;
}
if (typeof(T) == typeof(Manager2))
{
return new Manager2(managerID, withUsers) as T;
}
throw new ArgumentException();
}
当您说“给我managerID x的Manager *对象”时,某些地方必须知道/确定要创建哪种Manager类。 因此,需要回答的一个问题是如何做出决定。 这是由数据读取器返回的某种数据确定的吗?
您可以创建一个管理器Factory或Repository类,而不是使用“ GetManager”静态方法,该类可以了解如何确定给定数据读取器创建哪种类型的Manager对象。
下面是一个示例实现。 这个想法是,在某个早期阶段(例如,当您的应用程序启动时),您创建一个ManagerRepository,然后为您拥有的每种Manager类类型注册一个“创建”委托。 以后,当您从ManagerRepository请求一个Manager对象时,它将决定要返回哪种类型的Manager类,并将利用您为该类型注册的“创建”委托。
public class ManagerBase
{
}
class ManagerRepository
{
private Dictionary<Type, Func<SqlDataReader, ManagerBase>> _ManagerCreateDelegates;
public ManagerRepository()
{
_ManagerCreateDelegates = new Dictionary<Type, Func<SqlDataReader, ManagerBase>>();
}
public void RegisterCreate<T>(Func<SqlDataReader, ManagerBase> create)
where T : ManagerBase
{
_ManagerCreateDelegates[typeof(T)] = create;
}
public ManagerBase GetManager(int managerID, bool withUsers)
{
SqlDataReader reader;
reader = null;// TODO: obtain a data reader from somewhere...
Type typeOfManager = this.DetermineManagerType(reader);
Func<SqlDataReader, ManagerBase> create;
if (_ManagerCreateDelegates.TryGetValue(typeOfManager, out create))
{
return create(reader);
}
else
{
throw new InvalidOperationException(string.Format("No create delegate has been registered for type [{0}].", typeOfManager.FullName));
}
}
private Type DetermineManagerType(SqlDataReader reader)
{
// TODO: implement logic that uses the data reader to decide which type of Manager object to create
throw new NotImplementedException();
}
}
public class ManagerSomething1 : ManagerBase
{
public ManagerSomething1(SqlDataReader reader)
{
// TODO: implement logic to construct ManagerSomething1 given a data reader
}
}
public class ManagerSomething2 : ManagerBase
{
public ManagerSomething2(SqlDataReader reader)
{
// TODO: implement logic to construct ManagerSomething1 given a data reader
}
}
class Program
{
static void Main(string[] args)
{
// create a ManagerRepository somewhere
ManagerRepository repository = new ManagerRepository();
// register create delegates for each type of Manager
repository.RegisterCreate<ManagerSomething1>(dr => new ManagerSomething1(dr));
repository.RegisterCreate<ManagerSomething2>(dr => new ManagerSomething2(dr));
// use the repository
int managerID = 5;
bool withUsers = false;
ManagerBase manager = repository.GetManager(managerID, withUsers);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.