【问题标题】:C# type extends interfaceC# 类型扩展接口
【发布时间】:2010-06-21 10:20:07
【问题描述】:

我目前正在尝试从 web.config 文件中读取有关对象的信息,并基于此创建对象。但是,我只希望能够从扩展特定接口 (IModule) 的类中创建对象。对象的类型来自 web.config 中的类型属性:

  <module moduleAlias="Test" type="ASPNETMVCMODULES.TestModule" connectionStringName="ApplicationServices">
    <properties>
      <property name="prop1" value="abc" type="System.String"/>
      <property name="prop2" value="123" type="System.Int32"/>
    </properties> 
  </module>

在我的代码中,ASPNETMVCMODULES.TestModule 实际上扩展了IModule,它可以通过以下代码正常加载:

我遇到的问题是,因为我将每个对象都定义为IModule,所以我无法访问我添加到扩展类的任何其他方法或属性。我有什么方法可以创建具有自己类型的对象,同时确保它扩展IModule?使用System.Convert 是否值得将IModule 转换为TestModule(在这种情况下)?

理想情况下,我希望能够使用modT 定义对象,这是直接来自 web.config 的对象类型。

    public void LoadModules()
    {
        ASPNETMVCMODULES.Configuration.ModulesSection allModules = (ASPNETMVCMODULES.Configuration.ModulesSection)System.Web.Configuration.WebConfigurationManager.GetSection("mvcmodules");
        foreach (Configuration.Module mod in allModules.Modules)
        {
            Type modT = Type.GetType(mod.ModuleType);

            IModule ob = (IModule)Activator.CreateInstance(modT);
            foreach (ASPNETMVCMODULES.Configuration.ModuleProperty modP in mod.ModuleProperties)
            {
                object origVal = modP.Value;
                object newVal = Convert.ChangeType(origVal, Type.GetType(modP.PropertyTypeString));
                ob.Properties.Add(modP.Name, newVal);
            }

            //Have to add some properties manually
            ob.Properties.Add("ConnectionString", (string)mod.ConnectionString);

            //RegisterModule(string, IModule)
            RegisterModule(mod.ModuleAlias, ob);
        }
    }

谢谢

【问题讨论】:

    标签: c# interface types


    【解决方案1】:

    您可以使用以下代码确定一个类是否具有特定接口:

    public void LoadModules()
    {
       // ...
    
       Type modT = Type.GetType(mod.ModuleType);
       if (InheritsFromInterface(modT, typeof(IModule))
       {
          IModule ob = (IModule)Activator.CreateInstance(modT);   
           // ...
       }
    }
    
    public bool InheritsFromInterface(Type inheritor, Type interface)
    {
        Type result = inheritor.GetInterface(interface.FullName);
        return result != null;
    }
    

    希望这就是你所追求的。

    【讨论】:

    • 这肯定有助于确保只加载那些扩展接口的类,谢谢。但是,我在创建modT 的实例时仍然遇到问题。如果我不将Activator.CreateInstance(modT); 转换为IModule,那么稍后我将无法在代码中访问其方法和属性。
    • @AndyBrush - 我更新了答案。这是你的意思吗?这是您已经完成的,应该可以正常工作。
    • @GenericTypeTea 谢谢。此代码适用于从 web.config 加载所有模块,但是当我需要访问类型 modT 的任何其他方法或属性时,它开始挣扎。有没有办法显式创建modT 而不是IModule 的对象?也许与IModule ob = (IModule)Activator.CreateInstance(modT);类似?
    • @AndyBrush - 我认为你误解了 Activator 的工作原理。此外,您不是在创建 IModule,而是在创建继承 IModule 的类的实例。您不能创建接口。 System.Activator 将创建完整类型。 IE。 System.Activator(modT); 将返回一个对象,它是一个新的 modT 实例。仅仅因为你将它转换为 IModule 并不会将它变成一个 IModule。
    • @GenericTypeTea 是的,看来我误解了 Activator 的工作原理,谢谢。稍后在我的代码中,我需要能够访问特定于modT 的方法;例如:ViewData["USERNAME"] = Modules["Test"].TestDataConnection();。使用我当前的代码,我收到一条错误消息,指出 IModule 不包含 TestDataConnection 的定义(位于 TestModule 中)。这可能是我存储和检索这些对象的方式的结果吗?
    【解决方案2】:

    你有几个不同的选择,我自己用过这两个。

    1. 使用XmlSerializer
    2. 使用@987654322@ 创建一个实例,然后使用反射自己设置属性,PropertyInfo[] props = typeof(T).GetProperties() 并尝试在您创建的实例中查找属性。

    【讨论】:

    • 感谢您的输入,但我现在可以正确创建所有对象和设置属性。我的问题是输入这些对象;我需要它们与modT 中的类型相同,而不是IModule,这是它们扩展的接口,以便在后续代码中访问它们的属性和方法。
    猜你喜欢
    • 2021-08-07
    • 1970-01-01
    • 2021-08-07
    • 2015-04-01
    • 1970-01-01
    • 2022-12-06
    • 2017-12-07
    • 1970-01-01
    • 2020-05-04
    相关资源
    最近更新 更多