असल में वहाँ में अभिव्यक्ति पेड़ के साथ गुण और फ़ील्ड सेट करने के लिए एक तरीका है। नेट 3.5।
क्षेत्र के लिए चाल के रूप में रेफरी पैरामीटर क्षेत्र से गुजर रहा है,
उदहारण के लिए: यह कुछ पीसीएल प्रोफाइल के लिए एकमात्र विकल्प है कि Delegate.CreateDelegate
का समर्थन नहीं करते (Reflection.Emit के अलावा) हो सकता है SetField(ref holder.Field, "NewValue");
संपत्ति (जैसा कि पहले से ही मार्क द्वारा इंगित किया गया है) को इसके सेटर विधि को प्रतिबिंबित और कॉल करके सेट किया जा सकता है।
अवधारणा का पूरा सबूत एनयूनीट परीक्षण स्थिरता के रूप में नीचे प्रदान किया गया है।
[TestFixture]
public class CanSetPropAndFieldWithExpressionTreeInNet35
{
class Holder
{
public int Field;
public string Prop { get; set; }
}
public static class FieldAndPropSetter
{
public static T SetField<T, TField>(T holder, ref TField field, TField value)
{
field = value;
return holder;
}
public static T SetProp<T>(T holder, Action<T> setProp)
{
setProp(holder);
return holder;
}
}
[Test]
public void Can_set_field_with_expression_tree_in_Net35()
{
// Shows how expression could look like:
Func<Holder, Holder> setHolderField = h => FieldAndPropSetter.SetField(h, ref h.Field, 111);
var holder = new Holder();
holder = setHolderField(holder);
Assert.AreEqual(111, holder.Field);
var holderType = typeof(Holder);
var field = holderType.GetField("Field");
var fieldSetterMethod =
typeof(FieldAndPropSetter).GetMethod("SetField")
.MakeGenericMethod(holderType, field.FieldType);
var holderParamExpr = Expression.Parameter(holderType, "h");
var fieldAccessExpr = Expression.Field(holderParamExpr, field);
// Result expression looks like: h => FieldAndPropSetter.SetField(h, ref h.Field, 222)
var setHolderFieldExpr = Expression.Lambda<Func<Holder, Holder>>(
Expression.Call(fieldSetterMethod, holderParamExpr, fieldAccessExpr, Expression.Constant(222)),
holderParamExpr);
var setHolderFieldGenerated = setHolderFieldExpr.Compile();
holder = setHolderFieldGenerated(holder);
Assert.AreEqual(222, holder.Field);
}
[Test]
public void Can_set_property_with_expression_tree_in_Net35()
{
// Shows how expression could look like:
Func<Holder, Holder> setHolderProp = h => FieldAndPropSetter.SetProp(h, _ => _.Prop = "ABC");
var holder = new Holder();
holder = setHolderProp(holder);
Assert.AreEqual("ABC", holder.Prop);
var holderType = typeof(Holder);
var prop = holderType.GetProperty("Prop");
var propSet = prop.GetSetMethod();
var holderParamExpr = Expression.Parameter(holderType, "h");
var callSetPropExpr = Expression.Call(holderParamExpr, propSet, Expression.Constant("XXX"));
var setPropActionExpr = Expression.Lambda(callSetPropExpr, holderParamExpr);
var propSetterMethod = typeof(FieldAndPropSetter).GetMethod("SetProp").MakeGenericMethod(holderType);
// Result expression looks like: h => FieldAndPropSetter.SetProp(h, _ => _.Prop = "XXX")
var setHolderPropExpr = Expression.Lambda<Func<Holder, Holder>>(
Expression.Call(propSetterMethod, holderParamExpr, setPropActionExpr),
holderParamExpr);
var setHolderPropGenerated = setHolderPropExpr.Compile();
holder = setHolderPropGenerated(holder);
Assert.AreEqual("XXX", holder.Prop);
}
}
ग्रेट प्रतिक्रिया बैरी, आपने मेरे प्रारंभिक प्रश्न का उत्तर दिया। मैं एक और सवाल पोस्ट करने जा रहा हूं जहां मुझे रूपांतरण को कॉल करने के लिए ओप कोड चाहिए .... धन्यवाद! – TheSoftwareJedi
बस जिज्ञासा, इस दृष्टिकोण का अंतर सिर्फ सिस्टम का उपयोग कर रहा है। रिफ्लेक्शन और सदस्य इन्फोस संपत्ति सेट करने के लिए? – chakrit
चक्रित - यह तेज़ है। –