代码之家  ›  专栏  ›  技术社区  ›  Bevan

使用结构映射按名称创建类?

  •  2
  • Bevan  · 技术社区  · 14 年前

    如何使用structuremap根据存储在属性中的名称解析为接口的适当实现?

    在我的项目中,我有许多不同类型的小部件,每个小部件从 IWidget ,每个元素都用指定关联元素类型的属性进行修饰。

    举例说明:

    [Configuration("header")]
    public class HeaderWidget : IWidget { }
    
    [Configuration("linegraph")]
    public class LineGraphWidget : IWidget { }
    

    在处理我的(XML)配置文件时,我希望根据正在处理的元素的名称获取适当具体类的实例。

    public IWidget CreateWidget(XElement definition)
    {
        var kind = definition.Name.LocalName;
        var widget = // What goes here?
        widget.Configure(definition);
        return widget;
    }
    

    每个定义都会导致创建一个不同的小部件-我不需要或不希望共享实例。

    在过去,我编写了大量的代码来手工完成这类工作,包括为一个项目编写一个自定义的“Roll Your Own”IOC容器。然而,我在这个项目中的目标之一是精通结构图,而不是重新设计轮子。

    我想我已经设法设置了程序集的自动扫描,以便structuremap了解我所有的iWidget实现:

    public class WidgetRegistration : Registry
    {
        public WidgetRegistration()
        {
            Scan(
                scanner =>
                {
                    scanner.AssembliesFromApplicationBaseDirectory();
                    scanner.AddAllTypesOf<IWidget>();
                });
        }
    }
    

    但是,这并不是在structuremap中注册小部件的名称。我需要添加什么才能使我的方案工作?

    (当我试图在这个项目中使用结构图时,向我展示如何用不同的DI/IOC工具解决这个问题的答案仍然是有价值的。)

    更新

    我很肯定消费方面包括打电话 GetNamedInstance 这样地:

    public IWidget CreateWidget(XElement definition)
    {
        var kind = definition.Name.LocalName;
        var widget = ObjectFactory.GetNamedInstance<IWidget>(kind);
        widget.Configure(definition);
        return widget;
    }
    

    所以剩下的问题是如何在我的widgetregistration类中自动注册类型。

    2 回复  |  直到 14 年前
        1
  •  1
  •   ozczecho    14 年前

    我们实现了一个定制的扫描器:

        public class WidgetScanner : ITypeScanner
    {
        public void Process(Type type, PluginGraph graph)
        {
    

    然后使用扫描:

            Scan(y =>
            {
                y.AddAllTypesOf(typeof(IWidget));
                y.Assembly(Assembly.GetExecutingAssembly().FullName);
                y.With<WidgetScanner>();
            });
    

    …要获得一个实例:

    _container.GetInstance<IWidget>(name)
    
        2
  •  1
  •   Bevan    14 年前

    这就是我最终的结果——我所需要的一切都被结构图所支持。

    我的注册课程负责所有的脏活:

    public class DashboardRegistration : Registry
    {
        public DashboardRegistration()
        {
            Scan(
                scanner =>
                {
                    scanner.AssembliesFromApplicationBaseDirectory();
                    scanner.AddAllTypesOf<IDisplay>()
                        .NameBy(DashboardXml.DisplayElement);
                    scanner.AddAllTypesOf<IDataSource>()
                        .NameBy(DashboardXml.DataSourceElement);
                });
        }
    }
    

    这个 .NameBy() 接受提供所需名称的委托。

    DashboardXML类上的适当方法如下(代码节略):

    public static class DashboardXml
    {
        ...
    
        public static string DataSourceElement(Type type)
        {
            const string DataSourceSuffix = "DataSource";
    
            string result = type.Name;
            if (result.EndsWith(DataSourceSuffix))
            {
                result 
                    = result.Substring(0, result.Length - DataSourceSuffix.Length);
            }
    
            return result.ToLowerInvariant();
        }
    
        public static string DisplayElement(Type type)
        {
            const string DisplaySuffix = "Display";
    
            string result = type.Name;
            if (result.EndsWith(DisplaySuffix))
            {
                result 
                    = result.Substring(0, result.Length - DisplaySuffix.Length);
            }
    
            return result.ToLowerInvariant();
        }
    }