我有一个基类“ManagerBase”,它有一个通用的静态函数“GetManager。有两个类继承自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, ...);
}
}
答案 0 :(得分:3)
你可以重构这样的事情:
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);
}
}
答案 1 :(得分:2)
这样的事可能有用:
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, ...});
答案 2 :(得分:0)
我认为你正试图在你想要构建的类中实现某种工厂模式。
有两种方法可以实现:拥有一个知道如何构建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();
}
答案 3 :(得分:0)
当你说“给我managerID x的Manager *对象”时,某个地方必须知道/决定要创建哪种类型的Manager类。因此,需要回答的一个问题是如何做出决定。这是由数据读取器返回的某种数据决定的吗?
您可以创建一个管理器Factory或Repository类,而不是使用“GetManager”静态方法,该类了解如何在给定数据读取器的情况下确定要创建哪种类型的Manager对象。
以下是一个示例实现。这个想法是在早期的某个时刻,例如当您的应用程序启动时,您创建一个ManagerRepository,然后为您拥有的每种类型的Manager类注册一个“create”委托。稍后,当您从ManagerRepository请求Manager对象时,它将决定返回哪种类型的Manager类,并将使用您为该类型注册的“create”委托。
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);
}
}