2009-10-18 11 views
7

my recent question से, मैं डोमेन इंटरफ़ेस में कुछ मूर्ख तर्क सहित डोमेन मॉडल को केंद्रीकृत करने का प्रयास करता हूं। हालांकि, मुझे कुछ समस्या मिली है जिसमें कुछ गुणों को मान्य करने या शामिल करने की आवश्यकता है।सी # में चयनित गुणों को परिभाषित और एक्सेस करने का सबसे अच्छा तरीका क्या है?

असल में, मैं निम्नलिखित कोड की तरह अभिव्यक्ति वृक्ष का उपयोग कर सकता हूं। फिर भी, मुझे यह पसंद नहीं है क्योंकि जब मैं लैम्ब्डा अभिव्यक्ति बनाता हूं तो मुझे स्थानीय चर ("यू") को परिभाषित करने की आवश्यकता होती है। क्या आपके पास कोई स्रोत कोड है जो मुझसे छोटा है? इसके अलावा, मुझे चयनित गुणों को त्वरित रूप से एक्सेस करने के लिए कुछ विधि चाहिए।

public void IncludeProperties<T>(params Expression<Func<IUser,object>>[] selectedProperties) 
{ 
    // some logic to store parameter 
} 

IncludeProperties<IUser> 
(
    u => u.ID, 
    u => u.LogOnName, 
    u => u.HashedPassword 
); 

धन्यवाद,

उत्तर

9

lambdas कई परिदृश्यों के लिए महान हैं - लेकिन अगर आप उन्हें नहीं करना चाहते, शायद बस उन्हें का उपयोग नहीं करते? मुझे यह कहने से नफरत है, लेकिन सरल तारों की कोशिश की जाती है और परीक्षण किया जाता है, खासकर डेटा बाध्यकारी जैसे परिदृश्यों के लिए। यदि आप तेजी से पहुंच चाहते हैं, तो आप हाइपरडिस्क्रिप्टर को देख सकते हैं, या संपत्ति एक्सेसर्स को एक प्रतिनिधि को संकलित करने के तरीके हैं, या आप स्ट्रिंग से Expression बना सकते हैं और इसे संकलित कर सकते हैं (यदि आप एक ज्ञात हस्ताक्षर चाहते हैं तो एक कास्ट सहित object) (बहुत धीमी) DynamicInvoke पर कॉल करने के बजाए)।

बेशक, ज्यादातर मामलों में भी कच्चे प्रतिबिंब पर्याप्त तेज़ होते हैं, और बाधा नहीं होती है।

मैं सबसे सरल कोड से शुरू करने का सुझाव देता हूं, और यह वास्तव में तेज होने के बारे में चिंता करने से पहले धीमा है। यदि यह बहुत धीमी नहीं है, तो इसे न बदलें। उपर्युक्त विकल्पों में से कोई भी अन्यथा काम करेगा।


एक और विचार; यदि आप Expression उपयोग कर रहे हैं, तो आप की तरह कुछ कर सकता है:

public void IncludeProperties<T>(
    Expression<Func<T,object>> selectedProperties) 
{ 
    // some logic to store parameter 
} 

IncludeProperties<IUser>(u => new { u.ID, u.LogOnName, u.HashedPassword }); 

और फिर अभिव्यक्ति अलग ले?

public static void IncludeProperties<T>(
    Expression<Func<T, object>> selectedProperties) 
{ 
    NewExpression ne = selectedProperties.Body as NewExpression; 
    if (ne == null) throw new InvalidOperationException(
      "Object constructor expected"); 

    foreach (Expression arg in ne.Arguments) 
    { 
     MemberExpression me = arg as MemberExpression; 
     if (me == null || me.Expression != selectedProperties.Parameters[0]) 
      throw new InvalidOperationException(
       "Object constructor argument should be a direct member"); 
     Console.WriteLine("Accessing: " + me.Member.Name); 
    } 
} 
static void Main() 
{ 
    IncludeProperties<IUser>(u => new { u.ID, u.LogOnName, u.HashedPassword }); 
} 

एक बार जब आप MemberInfo रों (ऊपर में me.Member) पता है, व्यक्तिगत पहुँच के लिए अपने स्वयं के lambdas निर्माण तुच्छ होना चाहिए: थोड़ा tidier, कम से कम ... यहाँ कुछ नमूना विखंडन दिखा कोड है। उदाहरण के लिए (object करने के लिए एक डाली सहित एक भी हस्ताक्षर प्राप्त करने के लिए):

var param = Expression.Parameter(typeof(T), "x"); 
var memberAccess = Expression.MakeMemberAccess(param, me.Member); 
var body = Expression.Convert(memberAccess, typeof(object)); 
var lambda = Expression.Lambda<Func<T, object>>(body, param); 
var func = lambda.Compile(); 
+0

ओह, अच्छा एक :) –

+0

क्या करने के लिए सबसे अच्छा तरीका है त्वरित पहुंच के लिए चयनित गुण रखें? सूची ? –

+0

'सदस्यइन्फो 'ठीक होगा; 'Func ' (या 'Func ') ठीक होगा; एक 'संपत्ति डिस्क्रिप्टर' ठीक होगा (हाइपरडिस्क्रिप्टर के साथ esp।)। यह किसी भी तरह से काम करेगा ... –

1

यहाँ कम से कम अभिव्यक्ति मैं के साथ आ सकते हैं:

public static void IncludeProperties(Expression<Action<IUser>> selectedProperties) 
{ 
    // some logic to store parameter 
} 

public static void S(params object[] props) 
{ 
    // dummy method to get to the params syntax 
} 

[Test] 
public void ParamsTest() 
{ 
    IncludeProperties(u => S(
     u.Id, 
     u.Name 
     )); 

} 
+0

यदि आप किसी अज्ञात प्रकार और प्रारंभकर्ता का उपयोग करते हैं (मेरा अद्यतन उत्तर देखें) तो आपको डमी विधि की आवश्यकता नहीं है। कौन सा अच्छा है –

+0

हाँ, मैं अब देखता हूं :) –

संबंधित मुद्दे

 संबंधित मुद्दे