C# 字典<;十、 Func<;Y>&燃气轮机;从函数访问包含的词典<&燃气轮机;里面

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

这有点奇怪

我正在构建一个web应用程序,我正在构建一个简单的工厂模式来处理一些对象实例化。我不喜欢丑陋的大开关盒块,所以我倾向于这样做:

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]);
    }
}