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; }
}
我的问题是:
应该公开一个“真实的”Person对象还是我应该公开 是否为其创建视图模型SelectedPerson
- 如果首选
,我应该如何使用它ViewModel
访问权限实体框架
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; }
}
}