यदि आप वास्तव में कोड कोड लिखने के बिना संपत्ति सेटिंग्स को चेन करने में सक्षम होना चाहते हैं, तो ऐसा करने का एक तरीका कोड जनरेशन (कोडडॉम) का उपयोग करना होगा। आप परिवर्तनीय गुणों की एक सूची प्राप्त करने के लिए प्रतिबिंब का उपयोग कर सकते हैं, एक अंतिम Build()
विधि के साथ एक धाराप्रवाह बिल्डर वर्ग उत्पन्न करता है जो उस वर्ग को लौटाता है जिसे आप वास्तव में बनाने की कोशिश कर रहे हैं।
मैं कस्टम टूल को पंजीकृत करने के बारे में सभी बॉयलरप्लेट सामग्री को छोड़ने जा रहा हूं - यह दस्तावेज ढूंढना काफी आसान है लेकिन अभी भी लंबे समय तक हवादार है और मुझे नहीं लगता कि मैं इसे शामिल करके बहुत कुछ जोड़ रहा हूं । यद्यपि मैं कोडजन के लिए क्या सोच रहा हूं मैं आपको दिखाऊंगा।
public static class PropertyBuilderGenerator
{
public static CodeTypeDeclaration GenerateBuilder(Type destType)
{
if (destType == null)
throw new ArgumentNullException("destType");
CodeTypeDeclaration builderType = new
CodeTypeDeclaration(destType.Name + "Builder");
builderType.TypeAttributes = TypeAttributes.Public;
CodeTypeReference destTypeRef = new CodeTypeReference(destType);
CodeExpression resultExpr = AddResultField(builderType, destTypeRef);
PropertyInfo[] builderProps = destType.GetProperties(
BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo prop in builderProps)
{
AddPropertyBuilder(builderType, resultExpr, prop);
}
AddBuildMethod(builderType, resultExpr, destTypeRef);
return builderType;
}
private static void AddBuildMethod(CodeTypeDeclaration builderType,
CodeExpression resultExpr, CodeTypeReference destTypeRef)
{
CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
method.Name = "Build";
method.ReturnType = destTypeRef;
method.Statements.Add(new MethodReturnStatement(resultExpr));
builderType.Members.Add(method);
}
private static void AddPropertyBuilder(CodeTypeDeclaration builderType,
CodeExpression resultExpr, PropertyInfo prop)
{
CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
method.Name = prop.Name;
method.ReturnType = new CodeTypeReference(builderType.Name);
method.Parameters.Add(new CodeParameterDeclarationExpression(prop.Type,
"value"));
method.Statements.Add(new CodeAssignStatement(
new CodePropertyReferenceExpression(resultExpr, prop.Name),
new CodeArgumentReferenceExpression("value")));
method.Statements.Add(new MethodReturnStatement(
new CodeThisExpression()));
builderType.Members.Add(method);
}
private static CodeFieldReferenceExpression AddResultField(
CodeTypeDeclaration builderType, CodeTypeReference destTypeRef)
{
const string fieldName = "_result";
CodeMemberField resultField = new CodeMemberField(destTypeRef, fieldName);
resultField.Attributes = MemberAttributes.Private;
builderType.Members.Add(resultField);
return new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), fieldName);
}
}
मुझे लगता है कि यह होना चाहिए बस के बारे में यह कर - यह स्पष्ट रूप से अपरीक्षित है, लेकिन जहां तुम यहाँ से जाओ कि तुम एक codegen (BaseCodeGeneratorWithSite
से इनहेरिट) है कि एक CodeCompileUnit
प्रकार की एक सूची के साथ आबादी वाले संकलित पैदा करते हैं। वह सूची आपके द्वारा टूल के साथ पंजीकृत फ़ाइल प्रकार से आती है - इस मामले में मैं शायद इसे एक प्रकार की लाइन-डिलीमिटेड सूची के साथ एक टेक्स्ट फ़ाइल बनाउंगा जिसके लिए आप बिल्डर कोड जेनरेट करना चाहते हैं। उपकरण को स्कैन करें, प्रकारों को लोड करें (पहले असेंबली लोड करना पड़ सकता है), और बाइटकोड उत्पन्न करें।
यह रूप में यह लग रहा है कठिन है, लेकिन के रूप में कठिन नहीं है, और यह करने के बाद आप इस तरह कोड लिखने के लिए सक्षम हो जाएगा:
Paint p = new PaintBuilder().Red(0.4).Blue(0.2).Green(0.1).Build().Mix.Stir();
कौन सा मेरा मानना है कि लगभग बिल्कुल तुम क्या चाहते है।तुम सब कोड पीढ़ी आह्वान करने के लिए क्या करना है दर्ज होने वाले कस्टम विस्तार के साथ उपकरण (मान लीजिए कि .buildertypes
हैं), अपनी परियोजना में है कि एक्सटेंशन वाली फ़ाइल रखा, और डाल प्रकार की एक सूची में है:
MyCompany.MyProject.Paint
MyCompany.MyProject.Foo
MyCompany.MyLibrary.Bar
और इसी तरह। जब आप सहेजते हैं, तो यह स्वचालित रूप से उस कोड फ़ाइल को जेनरेट करेगा जो आपको आवश्यक है जैसे ऊपर दिए गए लेखन विवरणों का समर्थन करता है।
मैंने कई सौ अलग-अलग संदेश प्रकारों के साथ अत्यधिक संकलित संदेश प्रणाली के लिए इस दृष्टिकोण का उपयोग किया है। हमेशा संदेश बनाने, गुणों का एक गुच्छा सेट करने, चैनल के माध्यम से भेजने, चैनल से प्राप्त करने, प्रतिक्रिया को क्रमबद्ध करने आदि के लिए बहुत लंबा समय लग रहा था ... कोडजन का उपयोग करके काम को बहुत सरल बना दिया गया क्योंकि यह मुझे उत्पन्न करने में सक्षम बनाता था एकल मैसेजिंग क्लास जिसने सभी व्यक्तिगत गुणों को तर्क के रूप में लिया और सही प्रकार की प्रतिक्रिया वापस थूक दिया। ऐसा कुछ नहीं है जो मैं सभी को सलाह दूंगा, लेकिन जब आप बहुत बड़ी परियोजनाओं से निपट रहे हों, तो कभी-कभी आपको अपने स्वयं के वाक्यविन्यास का आविष्कार करना शुरू करना होगा!
वास्तव में मेरे पास मेरी परियोजनाओं में से एक में समान दृष्टिकोण है। –