2011-03-10 30 views
0

我想知道在c#中是否有某些東西能夠將一個類的成員傳遞給另一個將使用此成員來獲取值的函數。因此,只需在運行時獲取一個字段的值即可。像其他語言(PHP至少我認爲),你可以做作爲第一類對象的類成員

a.b = "something" 

而且

a["b"] = "something"; 

編輯:其實不是那麼好一個例子,因爲使用字符串,對不起

爲了清楚想要什麼,我能夠做一個例子:

class A 
{ 
    int x; 
    int y; 
} 

void somethingsomething<T>(T class, SomeMagicFieldClass f) 
{ 
    dosomethingwith(somemethodthatgivesmethevalueoffield(class, f)); 
} 

哪裏話,我可以調用滿足HOD這樣的:

A a = new A(); 
somethingsomething(a, A.x); //hypothetical notation 
somethingsomething(a, A.y); 

我現在也有類似的地方我做了什麼:

somethingsomething(a, "x"); 
somethingsomething(a, "y"); 

我然後去使用發現場內省API(也在努力的getProperty)

MemberInfo memberInfo = item.GetType().GetField(fieldName); 

該作品但缺點是作爲字符串傳遞的字段不會在Visual Studio中「重構」字段名時得到更新,所以我想也許在c#中存在這樣的東西,會得到重構的自動在更改字段名稱時,這是否是一個問

非常感謝您閱讀本無聊的問題

+0

幸運的是......不! :) – stefan 2011-03-10 16:39:14

+0

你總是可以使用枚舉來指定方法名稱,那麼你只需要在一個地方替換它......'somethingsomething(a,MyAClassProperties.X)' – 2011-03-10 16:39:36

回答

1

你可以用LINQ表達式來做一些不錯的重構友好事物。這裏是我用於這種場合的實用代碼片段。它允許您獲取屬性的名稱,類型和值(它不會與沒有修改的字段配合使用)。還有一個價值二傳手。

public static void Main(string[] args) { 
    var test = new { Test1 = 42, Test2 = "123", Test3 = 3.14195 }; 

    somethingSomething(test, t => t.Test1); 
    somethingSomething(test, t => t.Test2); 
    somethingSomething(test, t => t.Test3); 
} 

static void somethingSomething<TObj,TProperty>(TObj obj, Expression<Func<TObj,TProperty>> expr) { 
    var accessor = GetMemberAccessor(expr, obj); 

    String name = accessor.Name; 
    TProperty value = accessor.Value; 
    String typeName = accessor.Type.Name; 
    Console.WriteLine("{0} = {1} ({2})", name, value, typeName); 
} 

,它的輸出將是:

Test1 = 42 (Int32) 
Test2 = 123 (String) 
Test3 = 3.14195 (Double) 

爲了使這項工作,我用下面的輔助函數和類:

public static MemberAccessor<TReturn> GetMemberAccessor<TObj,TReturn>(Expression<Func<TObj, TReturn>> expr, TObj tar) { 
    var body = expr.Body; 

    MemberExpression memberExpression = null; 
    if (body is UnaryExpression) { 
     var ue = (UnaryExpression)body; 
     memberExpression = (MemberExpression)ue.Operand; 
    } else if (body is MemberExpression) 
     memberExpression = (MemberExpression)body; 
    else 
     throw new NotImplementedException("can't get MemberExpression"); 

    String name = memberExpression.Member.Name; 

    return new MemberAccessor<TReturn>(tar, name); 
} 

public class MemberAccessor<T> { 
    private readonly PropertyDescriptor propertyDesc; 
    private readonly Object target; 

    public MemberAccessor(Object target, String propertyName) { 
     this.target = target; 
     this.propertyDesc = TypeDescriptor.GetProperties(target)[propertyName]; 
    } 
    public String Name { 
     get { return propertyDesc.Name; } 
    } 
    public Type Type { 
     get { return propertyDesc.PropertyType; } 
    }   
    public T Value { 
     get { return (T)Convert.ChangeType(propertyDesc.GetValue(target), typeof(T)); } 
     set { propertyDesc.SetValue(target, value); } 
    } 
} 
4

你的榜樣看起來很像一個LINQ鍵選擇,在形式,它會是什麼樣子:

A a = new A(); 
somethingsomething(a, p => p.x); 
0

布朗克先生是正確的;一個動態類型將完成這項工作。幸運的是,.NET 4團隊包含一個名爲ExpandoObject的便利對象,可以爲您解決這個問題。

0

你問我如何

傳遞一個類將使用該成員 另一 的成員函數獲取值

您可以使用delegates這個

class A 
    { 
     public string aField; 

     public string aProperty{get{return "someval";}} 

     public string aMemberFunction(){return "someval";} 
    } 


    void get_a_value(Func<string> func) 
    { 
     string theValue = func(); 
    } 

    // use it: 
    A a = new A(); 

    get_a_value(() => a.aField); 
    get_a_value(() => a.aProperty); 
    get_a_value(() => a.aMemberFunction()); 

什麼你不這樣做,當然是成員函數的參數分離和你傳遞的對象。