我们正在创建自己的代码,以自动化CRUD编码,我们需要生成一个用于WPF的类。为此,我们需要创建具有字段/属性作为依赖项对象的类。我们如何使用.Net 3.5中的CodeDom实现这一目标?
答案 0 :(得分:1)
文章 - Three Ways to Implement Dependency Injection in .NET Applications
摘要:替换依赖项 依赖注入模式代码 让你的课程更容易测试和 重用
Dynamic Code Generation using CodeDOM
摘要:本文解释了如何 CodeDOM可用于生成代码 动态地使用动态构建它 代码编译。它还解释了如何 应用自定义属性。
答案 1 :(得分:0)
您可以使用以下内容动态生成依赖项对象,其依赖项属性来自词典。
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using Microsoft.CSharp;
namespace WpfApplication1
{
public class DependencyPropertyGenerator
{
public static Type Generate(Dictionary<string, Type> typeDef)
{
var codeCompileUnit = new CodeCompileUnit();
var codeNamespace = new CodeNamespace("Generated");
codeNamespace.Imports.Add(new CodeNamespaceImport("System"));
codeNamespace.Imports.Add(new CodeNamespaceImport("System.Windows"));
var codeTypeDeclaration = new CodeTypeDeclaration("DataObject")
{
IsClass = true,
TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed
};
codeTypeDeclaration.BaseTypes.Add(new CodeTypeReference(typeof (DependencyObject)));
codeNamespace.Types.Add(codeTypeDeclaration);
codeCompileUnit.Namespaces.Add(codeNamespace);
AddProperties(codeTypeDeclaration, typeDef);
return CompileAssembly(codeCompileUnit);
}
public static void AddProperties(CodeTypeDeclaration targetClass, Dictionary<string, Type> typeDef)
{
foreach (var pair in typeDef)
{
var dpProperty = new CodeMemberField
{
Name = pair.Key + "Property",
Attributes = MemberAttributes.Public | MemberAttributes.Static,
Type = new CodeTypeReference("DependencyProperty"),
InitExpression = new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("DependencyProperty"),
"Register",
new CodePrimitiveExpression(pair.Key),
new CodeTypeOfExpression(pair.Value),
new CodeTypeOfExpression(targetClass.Name),
new CodeObjectCreateExpression(typeof (PropertyMetadata),
new CodeDefaultValueExpression(new CodeTypeReference(pair.Value))))
};
targetClass.Members.Add(dpProperty);
var clrProperty = new CodeMemberProperty
{
Name = pair.Key,
Type = new CodeTypeReference(pair.Value),
Attributes = MemberAttributes.Public | MemberAttributes.Final
};
clrProperty.GetStatements.Add(
new CodeMethodReturnStatement(new CodeCastExpression(pair.Value,
new CodeMethodInvokeExpression(null, "GetValue",
new CodeFieldReferenceExpression(null, dpProperty.Name)))
));
clrProperty.SetStatements.Add(
new CodeMethodInvokeExpression(null, "SetValue",
new CodeFieldReferenceExpression(null, dpProperty.Name),
new CodePropertySetValueReferenceExpression()));
targetClass.Members.Add(clrProperty);
}
}
private static Type CompileAssembly(CodeCompileUnit compileUnit)
{
var compilerParameters = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true
};
var executingAssembly = Assembly.GetExecutingAssembly();
compilerParameters.ReferencedAssemblies.Add(executingAssembly.Location);
foreach (var assemblyName in executingAssembly.GetReferencedAssemblies())
{
compilerParameters.ReferencedAssemblies.Add(Assembly.Load(assemblyName).Location);
}
using (var provider = new CSharpCodeProvider())
{
var compileResults = provider.CompileAssemblyFromDom(compilerParameters, compileUnit);
var compiledAssembly = compileResults.CompiledAssembly;
return compileResults.Errors.Count > 0 ? null : compiledAssembly.GetType("Generated.DataObject");
}
}
}
}
以下是你如何使用它:
[Test]
public void GenerateTest()
{
var typeDictionary = new Dictionary<string, Type>
{
{"Field1", typeof (string)},
{"Field2", typeof (double)},
{"Field3", typeof (decimal)},
{"Field4", typeof (DateTime)},
{"Field5", typeof (float)}
};
var type = DependencyPropertyGenerator.Generate(typeDictionary);
foreach (var fieldName in typeDictionary.Keys)
{
var dp = DependencyPropertyDescriptor.FromName(fieldName, type, type);
Assert.IsNotNull(dp.DependencyProperty);
Assert.AreEqual(dp.DependencyProperty.Name,fieldName);
Assert.AreEqual(dp.DependencyProperty.PropertyType , typeDictionary[fieldName]);
}
}