C# 字典<;十、 Func<;Y>&燃气轮机;从函数访问包含的词典<&燃气轮机;里面
这有点奇怪 我正在构建一个web应用程序,我正在构建一个简单的工厂模式来处理一些对象实例化。我不喜欢丑陋的大开关盒块,所以我倾向于这样做:C# 字典<;十、 Func<;Y>&燃气轮机;从函数访问包含的词典<&燃气轮机;里面,c#,dictionary,this,C#,Dictionary,This,这有点奇怪 我正在构建一个web应用程序,我正在构建一个简单的工厂模式来处理一些对象实例化。我不喜欢丑陋的大开关盒块,所以我倾向于这样做: public enum Option { Option1, Option2, Option3 } public Dictionary<Option, Func<MyBaseClass>> OptionMapping = new Dictionary<Option, Func<MyBaseC
public enum Option
{
Option1,
Option2,
Option3
}
public Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>>
{
{ Option1, () => new DerivedClassOne() },
{ Option2, () => new DerivedClassTwo() },
{ Option3, () => new DerivedClassThree() }
};
但是LINQPad中的一个快速测试告诉我这不起作用,因为当然this
指的是编写代码的类,而不是字典(显然我花了太多时间在this
更易变的语言上)。我的第二个想法是将其更改为()=>OptionMapping[Option1]()
,但这会导致一个错误,即您试图在初始化它之前使用OptionMapping
。您当然可以这样做:
public Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>>
{
{ Option1, () => new DerivedClassOne() },
{ Option2, () => new DerivedClassTwo() }
};
OptionMapping.Add(Option3, () => OptionMapping [Option1]());
公共字典选项映射
=新词典
{
{Option1,()=>新的DerivedClassOne()},
{Option2,()=>new-DerivedClassTwo()}
};
OptionMapping.Add(Option3,()=>OptionMapping[Option1]());
这很管用,但没那么漂亮。所以,这个问题主要是出于好奇
有没有办法从另一个字典中访问的一个元素?更一般地说,C#是否有像this
这样的关键字,意思是“执行时我现在就在里面的对象”,而不是“写入时包含的对象”
编辑:
最初,字典是静态的,所以在初始化之前我提到的关于使用它的错误不会发生。静态
实际上是粘贴在一个较大的代码块中并向下编辑它,然后复制粘贴错误的结果
因此,发布的主要答案是关于使用一个单独的对象来存储Func
,然后将其添加到字典中两次。这是有道理的,这或多或少是我最后所说的(出于各种原因,它还使一些周围的代码变得更清晰),但它避免了我最感兴趣的问题的一部分,即在C中是否有可能在运行时访问您所在的对象,以便对象可以访问字典(或列表或数组等)它们当前所在的位置。对于一般情况,不存在您所描述的内容。但是,对于您的特定情况,您的词典存储在一个静态
字段中,因此您应该可以通过该字段访问它:
public static Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>>
{
{ Option1, () => new DerivedClassOne() },
{ Option2, () => new DerivedClassTwo() },
{ Option3, () => OptionMapping[Option1]() }
};
在这种情况下,OptionMapping
被初始化的事实足以避免问题。初始化器不必是您要存储的字典。这应该可以:
private static Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>> {
{ Option.Option1, () => new DerivedClassOne() },
{ Option.Option2, () => new DerivedClassTwo() },
{ Option.Option3, () => OptionMapping[Option.Option2]() }
};
我会尽量减少使用静力学,如:
创建一个对象来保存此映射。它还可以执行函数来实际实例化类,即实际执行Func
。从外部调用方不知道映射是如何执行的,允许您稍后用DI容器或其他构造方法替换它:我还添加了一个接口to帮助您了解如何添加其他实现并在运行时注入它们。这对于测试也很有用
public interface IOptionFactory
{
MyBaseClass Create(Option option);
}
public sealed class OptionFactory : IOptionFactory
{
private readonly Dictionary<Option, Func<MyBaseClass>> _optionMapping;
public OptionFactory()
{
Func<MyBaseClass> makeDerivedTwo = () => new DerivedClassTwo();
_optionMapping = new Dictionary<Option, Func<MyBaseClass>>
{
{ Option.Option1, () => new DerivedClassOne() },
{ Option.Option2, makeDerivedTwo },
{ Option.Option3, makeDerivedTwo }
};
}
public MyBaseClass Create(Option option)
{
return _optionMapping[option]();
}
}
然后你需要问自己,我需要它是静态的吗?我可以注入IOptionFactory
下面是在Unity中使用依赖项注入时,IOptionFactory
的实现示例
public sealed class UnityOptionFactory : IOptionFactory
{
private readonly IUnityContainer _container;
private readonly Dictionary<Option, Type> _optionMapping;
public UnityOptionFactory(IUnityContainer container)
{
var makeDerivedTwo = typeof(DerivedClassTwo);
_optionMapping = new Dictionary<Option, Type>
{
{ Option.Option1, typeof(DerivedClassOne) },
{ Option.Option2, makeDerivedTwo },
{ Option.Option3, makeDerivedTwo }
};
}
public MyBaseClass Create(Option option)
{
return _container.Resolve(_optionMapping[option]);
}
}
公共密封类UnityOptionFactory:IOptionFactory
{
专用只读IUnityContainer\u容器;
专用只读词典_optionMapping;
公共单元选项工厂(IUnityContainer容器)
{
var makeDerivedTwo=类型(DerivedClassTwo);
_optionMapping=新字典
{
{Option.Option1,typeof(DerivedClassOne)},
{Option.Option2,makederivedtow2},
{Option.Option3,makederivedtow2}
};
}
公共MyBaseClass创建(选项)
{
返回_container.Resolve(_optionMapping[option]);
}
}
优点是,Unity正在创建这些类型,因此您可以将它们注入到构造函数中
private static Dictionary<Option, Func<MyBaseClass>> OptionMapping;
static MyClass() {
Func<MyBaseClass> makeDerivedTwo = () => new DerivedClassTwo();
OptionMapping = new Dictionary<Option, Func<MyBaseClass>> {
{ Option.Option1, () => new DerivedClassOne() },
{ Option.Option2, makeDerivedTwo },
{ Option.Option3, makeDerivedTwo }
};
}
public interface IOptionFactory
{
MyBaseClass Create(Option option);
}
public sealed class OptionFactory : IOptionFactory
{
private readonly Dictionary<Option, Func<MyBaseClass>> _optionMapping;
public OptionFactory()
{
Func<MyBaseClass> makeDerivedTwo = () => new DerivedClassTwo();
_optionMapping = new Dictionary<Option, Func<MyBaseClass>>
{
{ Option.Option1, () => new DerivedClassOne() },
{ Option.Option2, makeDerivedTwo },
{ Option.Option3, makeDerivedTwo }
};
}
public MyBaseClass Create(Option option)
{
return _optionMapping[option]();
}
}
private static IOptionFactory OptionMapping = new OptionFactory();
public sealed class UnityOptionFactory : IOptionFactory
{
private readonly IUnityContainer _container;
private readonly Dictionary<Option, Type> _optionMapping;
public UnityOptionFactory(IUnityContainer container)
{
var makeDerivedTwo = typeof(DerivedClassTwo);
_optionMapping = new Dictionary<Option, Type>
{
{ Option.Option1, typeof(DerivedClassOne) },
{ Option.Option2, makeDerivedTwo },
{ Option.Option3, makeDerivedTwo }
};
}
public MyBaseClass Create(Option option)
{
return _container.Resolve(_optionMapping[option]);
}
}