2016-08-24 85 views
0

我正在做一个属性类,它需要一个通用的。这个泛型应该是用户创建的类,它模仿配置文件中的appSettings部分。他们为每个键创建一个属性,这个属性让他们将该键映射到该字段。当他们使用他们的类实例化我的类作为泛型时,我会遍历他们的类来查找我的属性,并在发现时使用它们设置的名称来查找appSetting键,然后将该属性值设置为该appSetting值,同时将其转换为任何他们设置属性。在C#中更改一个属性为只读在运行时

所以基本上这是一个映射属性强烈类型的appSettings在配置文件中。它使得映射是在一个类中完成的,而不是用户必须在代码中进行内联并使其混乱。好的和干净的映射。

我最后一步是我想将它们的属性标记为只读,但我无法弄清楚如何做到这一点,因为PropertyInfo类的CanWrite属性本身是只读的。

/// <summary> 
    /// This class will fill in the fields of the type passed in from the config file because it's looking for annotations on the type 
    /// </summary> 
    public class StrongConfiguration<T> where T: class 
    { 
     // this is read only 
     public T AppSettings { get; private set; } 

     public StrongConfiguration() 
     { 
      AppSettings = (T)Activator.CreateInstance(typeof(T)); 

      // find properties in this type that have the ConfigAttribute attribute on them 
      var props = from p in AppSettings.GetType().GetProperties() 
         let attr = p.GetCustomAttributes(typeof(ConfigAttribute), true) 
         where attr.Length == 1 
         select new { Property = p, Attribute = attr.First() as ConfigAttribute }; 

      // find the config setting from the ConfigAttribute value on each property and set it's value casting to the propeties type 
      foreach (var p in props) 
      { 
       var appSettingName = ConfigurationManager.AppSettings[p.Attribute.ConfigName]; 

       var value = Convert.ChangeType(appSettingName, p.Property.PropertyType); 

       p.Property.SetValue(AppSettings, value); 

       // todo: I want to set this propety now as read-only so they can't change it but not sure how 
      } 
     } 
    } 
+0

这是你可能想使用'Emit'并将其代理出来的地方。你不能在运行时修改元数据...... – code4life

+0

从来没有听说过Emit,但它看起来像一个全新的世界。我会深入挖掘。 – user441521

+1

反对的任何理由?我做错了什么?很高兴知道以供将来参考。 – user441521

回答

2

两件事,一个C#不允许泛型属性类。所以这是行不通的。

其次,你不能改变的属性只在运行时阅读。反射是用于检查加载类型的元数据,而不是更改元数据。

你可以回自己的属性,但是这是一个更大的努力。

+0

对不起,我应该更清楚,这不是属性类,它是app.config中强类型appSettings的实际“库”类。属性类是独立于此的,但是这完成了读取配置文件并确定要在用户传入的基本类型中获得哪些属性的所有工作,这些属性基于用我的属性装饰的属性。在运行时,你不能改变为只读模式。你是什​​么意思回自己的财产?在Component类中还有ReadOnly属性,是否不会将所述属性更改为只读? – user441521

+1

要在运行时将属性标记为只读,可以使用'Reflection.Emit'或'Mono.Cecil'。但是我没有看到私人财产访问者的任何问题。为什么你需要准确的只读修饰符?你想避免任何人通过反射设置属性?但我认为没关系,如果有人尝试它,所以它确实需要他 – Serg046

+0

@ Serg046我想一般我在想,因为app.config是(大部分)意味着只读,这些属性也应该是只读。如果不是时代的终结,而只是试图更加标准化app.config的概念。 – user441521