我们如何使用.Net CodeDom创建依赖对象?

时间:2009-08-20 14:17:07

标签: c# .net codedom

我们正在创建自己的代码,以自动化CRUD编码,我们需要生成一个用于WPF的类。为此,我们需要创建具有字段/属性作为依赖项对象的类。我们如何使用.Net 3.5中的CodeDom实现这一目标?

2 个答案:

答案 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]);
        }
    }