2016-08-24 84 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