C# MVVM中的包装模型

C# MVVM中的包装模型,c#,wpf,mvvm,ef-code-first,C#,Wpf,Mvvm,Ef Code First,这个问题最初是从开始的,为了避免重复,我不会把它全部粘贴在这里。因此,在我收到第一个问题的答案后,我还有一个问题: 我应该如何包装我的业务对象(用作实体框架代码优先模型),以便我可以包含一些仅与特定模型相关的属性,以及我应该如何从我的视图模型中公开它?如何将更改保存回原始的型号 编辑: 仍在与此抗争,因此我添加了一个小的可复制示例: //class used as an EF code first model public class Person { public int Person

这个问题最初是从开始的,为了避免重复,我不会把它全部粘贴在这里。因此,在我收到第一个问题的答案后,我还有一个问题:
我应该如何包装我的
业务对象
(用作
实体框架代码优先模型
),以便我可以包含一些仅与特定模型相关的属性,以及我应该如何从我的
视图模型
中公开它?如何将更改保存回原始的
型号

编辑:
仍在与此抗争,因此我添加了一个小的可复制示例:

//class used as an EF code first model
public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public virtual ObservableCollection<Order> Orders { get; set; }
}
我的问题是:

  • SelectedPerson
    应该公开一个“真实的”Person对象还是我应该公开 是否为其创建视图模型
  • 如果首选
    ViewModel
    ,我应该如何使用它
    实体框架
    访问权限

我想你不能改变原来的型号

在我的一个项目中,我使用T4模板增强了原始模型。类(由生成器)修改,但不包含源文件

例如,这是原始代码:

public partial class ImprimanteSNData
{
    [T4Order(2)]
    private Boolean isConnected;

    [T4Order(0)]
    private List<String> printer;

    [T4Order(1)]
    private String serialNumber;
}

这只是一个示例,但它表明,在不修改原始代码的情况下,可以使用T4做很多事情。

您考虑过T4模板吗?@Xaruth这适用于
代码优先
场景?T4生成可以在您需要时进行,所以,当源代码或预构建中有修改时,您就可以执行它。@Xaruth在过去几天里试图学习和使用T4模板,但我觉得不太舒服。非常感谢。
public partial class ImprimanteSNData
{
    [T4Order(2)]
    private Boolean isConnected;

    [T4Order(0)]
    private List<String> printer;

    [T4Order(1)]
    private String serialNumber;
}
[DataContract]
public partial class ImprimanteSNData : IExtensibleDataObject
{
    private ExtensionDataObject extensionDataObjectValue;

    public ExtensionDataObject ExtensionData
    {
        get { return this.extensionDataObjectValue; }
        set { this.extensionDataObjectValue = value; }
    }

    [DataMember(Order = 2)]
    public System.Boolean IsConnected
    {
        get 
        {
            return this.isConnected;
        }

        set 
        {
            this.isConnected = value;
        }
    }

    [DataMember(Order = 0)]
    public System.Collections.Generic.List<System.String> Printer
    {
        get 
        {
            return this.printer ?? new System.Collections.Generic.List<System.String>();
        }

        set 
        {
            this.printer = value;
        }
    }

    [DataMember(Order = 1)]
    public System.String SerialNumber
    {
        get 
        {
            return this.serialNumber == null ? String.Empty : this.serialNumber.Trim();
        }

        set 
        {
            this.serialNumber = value;
        }
    }

}
<#@ template language="C#" debug="true" hostSpecific="true" #>
<#@ output extension=".cs" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ Assembly Name="System.Xml.dll" #>
<#@ Assembly Name="System.Xml.Linq.dll" #>
<#@ Assembly Name="System.Windows.Forms.dll" #>
<#@ Assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #> 
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Runtime.Serialization" #>
<#@ import namespace="XXXXXXXXXXX" #>
<#@ import namespace="System.Runtime.Serialization" #>
<#@ Assembly Name="$(ProjectDir)\bin\$(ConfigurationName)\FicheSignaletiqueViseoData.dll" #>
// T4Class : Génération des accesseurs de toutes les classes de FicheSignaletiqueViseoData
// pour les types non génériques et les classes, on rajoute une protection contre le null
// pour les String, on rajoute une protection contre le null et un Trim automatique
// Date de génération : <#= System.DateTime.Now.ToString() #>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

<#   
    const String BusinessEntityNamespace= "XXXXXXXXXXX";

    WriteLine("namespace {0}", BusinessEntityNamespace);
    WriteLine("{");
    PushIndent("\t");

    String T4TemplatePath = Path.GetDirectoryName(Host.TemplateFile);
    String dataContractSource = Path.Combine(T4TemplatePath, "DataContract");
    String[] sources = Directory.GetFiles(dataContractSource, "*.cs");
    IServiceProvider hostServiceProvider = (IServiceProvider)Host;
    EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));

    foreach(string file in sources)
    {
        EnvDTE.ProjectItem projectItem = dte.Solution.FindProjectItem(file);

        FileCodeModel fileCodeModel = projectItem.FileCodeModel;

        if (fileCodeModel != null)
        {
            foreach (CodeElement codeElement in fileCodeModel.CodeElements)
            {
                if (codeElement is CodeNamespace)
                {
                    CodeNamespace nsp = codeElement as CodeNamespace;
                    foreach (CodeElement subElement in nsp.Children)
                    {
                        if (subElement is CodeClass)
                        {
                            CodeClass classe = subElement as CodeClass;
                            if (classe.Access == vsCMAccess.vsCMAccessPublic && classe.Name.StartsWith("T4") == false && classe.Name != "Important")
                            {
                                GenerateClassFromCode(classe);
                            }
                        }
                    }
                }
            }
        }
    }

    PopIndent();
    WriteLine("}");
#>


<#+  
    private void GenerateClassFromCode(CodeClass classToGenerate)
    {
        WriteLine("[DataContract]");
        WriteLine("public partial class {0} : IExtensibleDataObject", classToGenerate.Name);
        WriteLine("{");
        PushIndent("\t");

        WriteLine("private ExtensionDataObject extensionDataObjectValue;");
        WriteLine(String.Empty);
        WriteLine("public ExtensionDataObject ExtensionData");
        WriteLine("{");
        PushIndent("\t");
        WriteLine("get { return this.extensionDataObjectValue; }");
        WriteLine("set { this.extensionDataObjectValue = value; }");
        PopIndent();
        WriteLine("}"); 
        WriteLine(String.Empty);

        List<Tuple<string, Int16>> checkOrder = new List<Tuple<string, Int16>>();

        List<CodeVariable> listVariable = new List<CodeVariable>();
        List<CodeEnum> listEnum = new List<CodeEnum>();

        foreach (CodeElement elem in classToGenerate.Members)
        {
            if (elem is CodeVariable)
            {
                listVariable.Add(elem as CodeVariable);
            }

            if (elem is CodeEnum)
            {
                listEnum.Add(elem as CodeEnum);
            }
        }

        foreach(CodeVariable variable in listVariable)
        {
            if (variable.Access == vsCMAccess.vsCMAccessPrivate)
            {
                // attributs
                foreach (CodeAttribute attribut in variable.Attributes)
                {
                    Int16 order = getPropertyOrderFromCode(attribut);
                    if (order >= 0)
                    {
                        if (checkOrder.Where(c => c.Item2 == order).Count() > 0)
                        {
                            WriteLine("// Ci dessous, erreur de compilation voulue. Veuillez corriger et recompiler.");
                            WriteLine("ERROR : Dans la classe " + classToGenerate.Name + ", doublon sur le T4Order " + order + " (utilisé par " + checkOrder.Where(c => c.Item2 == order).First().Item1 + ")");
                        }
                        else
                        {
                            WriteLine("[DataMember(Order = {0})]", order);
                            checkOrder.Add(new Tuple<string, Int16>(variable.Name, order));
                        }
                    }
                    else
                    {
                        Write("[" + attribut.FullName);
                        if(attribut.Children != null && attribut.Children.Count > 0)
                        {
                            TextPoint start = attribut.Children.Cast<CodeElement>().First().GetStartPoint();
                            TextPoint finish = attribut.GetEndPoint();
                            String allArguments = start.CreateEditPoint().GetText(finish);
                            Write("(" + allArguments);
                        }

                        WriteLine("]");   
                    }                   
                }

                // variable
                string propertyTypeStr = variable.Type.AsFullName;
                Type type = Type.GetType(propertyTypeStr);

                WriteLine("public {0} {1}", propertyTypeStr, MakeUpper(variable.Name));
                WriteLine("{");
                PushIndent("\t");

                    // getter
                    WriteLine("get ");
                    WriteLine("{");
                    PushIndent("\t");
                        if (propertyTypeStr == "System.String")
                        {
                            WriteLine("return this.{0} == null ? String.Empty : this.{0}.Trim();", variable.Name, propertyTypeStr);
                        }
                        else if (listEnum.Select(e => e.FullName).Contains(propertyTypeStr))
                        {
                            WriteLine("return this.{0};", variable.Name);
                        }
                        else if (type == null || ((type.IsGenericType || type.IsClass)))
                        {
                            WriteLine("return this.{0} ?? new {1}();", variable.Name, propertyTypeStr);
                        }
                        else
                        {
                            WriteLine("return this.{0};", variable.Name);
                        }

                    PopIndent();
                    WriteLine("}");     
                    WriteLine(String.Empty);

                    // setter
                    WriteLine("set ");
                    WriteLine("{");
                    PushIndent("\t");
                        WriteLine("this.{0} = value;", variable.Name);
                    PopIndent();
                    WriteLine("}"); 
                PopIndent();
                WriteLine("}"); 
                WriteLine(String.Empty);
            }
        }

        PopIndent();
        WriteLine("}");
        WriteLine(String.Empty);
    }

    private Int16 getPropertyOrderFromCode(CodeAttribute member)
    {
        if (member != null)
        {
            if (member.FullName == typeof(T4Order).ToString())
            {
                return Convert.ToInt16(member.Value);
            }
        }

        return -1;
    }

    private String MakeUpper(String name)
    {
        return name.Substring(0, 1).ToUpper() + name.Substring(1, name.Length-1);
    }
#>
public class T4Order : Attribute
{
    private Int16 order;

    public T4Order(Int16 o)
    {
        this.order = o;
    }

    public Int16 Order
    {
        get { return this.order; }
        set { this.order = value; }
    }
}