我有一个程序需要从各种表单执行一些操作。我想把行动放在一个集中的空间里。每个操作都有自己的类,该类派生自一个接口。
每个动作仅实例化一次,但用于各种场所,如上下文菜单,功能区,工具栏等。
我有以下代码工作,我想在制作列表时摆脱typeof。我希望有强烈的打字,没有反思和重构的可能性。
这可以更有效率吗?
class Program
{
static void Main(string[] args)
{
ActionManager actionManager = new ActionManager();
List<SomeInterface> listA = actionManager.CreateList(typeof(Do_A), typeof(Do_B));
List<SomeInterface> listB = actionManager.CreateList(typeof(Do_A), typeof(Do_B));
}
}
public class ActionManager
{
private Dictionary<Type, SomeInterface> instantiatedActions = new Dictionary<Type, SomeInterface>();
public List<SomeInterface> CreateList(params Type[] actions)
{
List<SomeInterface> theList = new List<SomeInterface>();
foreach (Type type in actions)
{
if(!instantiatedActions.ContainsKey(type))
{
instantiatedActions.Add(type, (SomeInterface)Activator.CreateInstance(type));
}
theList.Add(instantiatedActions[type]);
}
return theList;
}
}
public interface SomeInterface
{
}
public class Do_A : SomeInterface
{
}
public class Do_B : SomeInterface
{
}
public class Do_C : SomeInterface
{
}
答案 0 :(得分:2)
如果尚未看到类型,您可以创建返回类型的表达式。这将允许您保持强类型,并强制只允许传入SomeInterface实现。
static void Main(string[] args)
{
ActionManager actionManager = new ActionManager();
List<SomeInterface> listA = actionManager.CreateList<SomeInterface>(
() => new Do_A(), () => new Do_B());
List<SomeInterface> listB = actionManager.CreateList<SomeInterface>(
() => new Do_A(), () => new Do_B());
}
public class ActionManager
{
private Dictionary<Type, SomeInterface> instantiatedActions =
new Dictionary<Type, SomeInterface>();
public List<SomeInterface> CreateList<T>(params Expression<Func<T>>[] actions)
{
List<SomeInterface> theList = new List<SomeInterface>();
foreach (var action in actions)
{
var type = GetObjectType<T>(action);
if(!instantiatedActions.ContainsKey(type))
{
instantiatedActions.Add(type, (SomeInterface)action.Compile().Invoke());
}
theList.Add(instantiatedActions[type]);
}
return theList;
}
private static Type GetObjectType<T>(Expression<Func<T>> expr)
{
if ((expr.Body.NodeType == ExpressionType.Convert) ||
(expr.Body.NodeType == ExpressionType.ConvertChecked))
{
var unary = expr.Body as UnaryExpression;
if (unary != null)
return unary.Operand.Type;
}
return expr.Body.Type;
}
}
警告需要编译表达式以调用它并需要从表达式树返回类型。但是,根据您的评论,它仅在尚未看到类型时确保延迟实例化,并保证类型安全。