【问题标题】:Abstract factory add to dictionary from config抽象工厂从配置添加到字典
【发布时间】:2012-07-27 18:59:21
【问题描述】:

您好,我的工厂代码是这样的。我不想将这些值直接存储在字典中,而是将这些值存储在 app.config 文件中。如下所示。

public class HandlerFactory
    {
        private Dictionary<string, IHandler> _handlers = new Dictionary<string,IHandler>();
        public HandlerFactory()
        {
            _handlers.Add("AMOUNT", new AmountValidator());
            _handlers.Add("FLOW", new FlowValidator());
        }
        public IHandler Create(string key)
        {
            IHandler result;
            _handlers.TryGetValue(key, out result);
            return result;
        }
    }

我想将这些设置移动到我的配置文件中,如下所示。

  <?xml version="1.0" encoding="utf-8" ?>
        <configuration>
        <configSections>
            <section name="Indentifiers" type="System.Configuration.AppSettingsSection"/>
        </configSections>
        <Indentifiers>
            <add key="AMOUNT" value="AmountValidator" />
            <add key="FLOW" value="FlowValidator" />
        </Indentifiers>
    </configuration>

我正在做这样的事情,但我没有成功。不知道如何添加到字典中

NameValueCollection settings = ConfigurationManager.GetSection("Indentifiers") as NameValueCollection;
                if (settings != null)
                {
                    foreach (string key in settings.AllKeys)
                    {
                        _handlers.Add(key.ToString(), settings[key].ToString()); <-- how to handle here
                    }
                 }

【问题讨论】:

  • Activator.CreateInstance 在这里应该很有用。
  • 嗨混沌,我在我的主类而不是工厂类中调用 createInstance。在我的主课中,我正在做这样的事情' IHandler validator = handle.Create(arInfo[0].ToString()); IHandler handler = (IHandler)Activator.CreateInstance("Validation", validator.ToString()).Unwrap();'但我不明白如何将键的值转换为 IHandler 类型。 IE。在我的工厂类中从“AmountValidator”到“Ihandler 类型的 AmountValidator”。你明白我的意思吗?可以请教吗?
  • 我认为您不了解工厂的目的。考虑一下定义。汽车厂会生产汽车的蓝图还是实际的汽车?

标签: c# configuration dictionary abstract-factory


【解决方案1】:

正如 ChaosPandion 所指出的,CreateInstance 方法应该很有用。 假设您的两种处理程序类型都实现了 IHandler,并且它们位于正在运行的程序集中,

_handler.Add(key.ToString(), Activator.CreateInstance(null, settings[key].ToString()));

应该做的伎俩! http://msdn.microsoft.com/en-us/library/d133hta4.aspx 第一个参数是程序集的名称,null 默认为正在执行的程序集。

【讨论】:

  • 嗨olagjo,我不想在我的工厂类上创建实例,而是在我的主类中创建实例。如图' HandlerFactorys handle = new HandlerFactorys(); if (handle.isValid(arInfo[0].ToString())) { IHandler 验证器 = handle.Create(arInfo[0].ToString()); IHandler handler = (IHandler)Activator.CreateInstance("Validation", validator.ToString()).Unwrap(); handler.Validate(消息); }' 但问题是当我从配置中读取时如何将字符串转换为 Type Ihandler?你得到我的问题了吗?
【解决方案2】:
public interface IHandler
{
    void Handle();
}

public sealed class HandlerFactory
{
    private readonly Dictionary<string, Type> _map = new Dictionary<string, Type>();

    public HandlerFactory()
    {
        var handlers = (NameValueCollection)ConfigurationManager.GetSection("Handlers");
        if (handlers == null)
            throw new ConfigurationException("Handlers section was not found.");
        foreach (var key in handlers.AllKeys)
        {
            var typeName = handlers[key] ?? string.Empty;
            // the type name must be qualified enough to be 
            // found in the current context.
            var type = Type.GetType(typeName, false, true);
            if (type == null)
                throw new ConfigurationException("The type '" + typeName + "' could not be found.");
            if (!typeof(IHandler).IsAssignableFrom(type))
                throw new ConfigurationException("The type '" + typeName + "' does not implement IHandler.");
            _map.Add(key.Trim().ToLower(), type);
        }
    }

    // Allowing your factory to construct the value 
    // means you don't have to write construction code in a million places.
    // Your current implementation is a glorified dictionary
    public IHandler Create(string key)
    {
        key = (key ?? string.Empty).Trim().ToLower();
        if (key.Length == 0)
            throw new ArgumentException("Cannot be null or empty or white space.", "key");
        Type type;
        if (!_map.TryGetValue(key, out type))
            throw new ArgumentException("No IHandler type maps to '" + key + "'.", "key");
        return (IHandler)Activator.CreateInstance(type);
    }
}

【讨论】:

  • 感谢 Chaos,我在“'Validation.BuyValidator' 类型没有实现 IHandler,即使它实现了 IHandler。”时遇到错误。我的配置文件就像
  • @bayyinah - 如果您仔细查看我的原始代码,您会注意到 if 语句检查类型是否实现 IHandler 需要被否定。
猜你喜欢
  • 1970-01-01
  • 2016-03-31
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 2014-01-14
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
相关资源
最近更新 更多