gpt4 book ai didi

c# - 如何创建自定义值注入(inject)以将我的实体映射到我的 View 模型?包括尝试

转载 作者:太空宇宙 更新时间:2023-11-03 11:15:23 24 4
gpt4 key购买 nike

我正在尝试使用 ValueInjector(NuGet 的最新版本)将来自 EntityFramework Code First 对象的数据注入(inject)我的 View 模型。我也想做相反的事情,但这是我开始的尝试。

我研究了各种映射并尝试了很多。我还没有找到一个可以满足我需要的东西,我认为我的需求是一个相当基本的问题(SO 上有几个这样的问题,每个问题似乎都有不同的答案,这很好。)。

我真的尝试过对此进行尽职调查。我用谷歌搜索和浏览了 CodePlex 并下载了 ProDinner 应用程序(启动并运行它并逐步调试代码)。

我现在有自己的 ValueInjection 类来处理注入(inject)。我将以一种非常友好的方式粘贴我的代码和对象,以便您可以获取并运行它们。请注意,我有一个使用基本 LoopValueInjection 的解决方案,但我不喜欢它,因为它需要手动管道进行从实体到映射然后映射到实体的注入(inject)。 ProDinner 示例采用了一种更加模板化的方法,我喜欢这种方法,但我无法根据自己的需要对其进行调整。

我认为我的代码在逻辑上困惑的地方在于,如果源属性类型不是简单对象,我不明白如何强制进行递归注入(inject)。在此示例中,Person.Address.* 属性将按 PersonViewModel 类中的名称和类型进行匹配;然而,注入(inject)循环遍历 Person 的属性并尝试匹配 Person.Address 属性的名称和类型。

我以为行

        Object result = Activator.CreateInstance(c.SourceProp.Type)
.InjectFrom<CloneInjection>(c.SourceProp.Value);

会执行此递归,但我认为不会。

那么...谁能告诉我如何解决这个问题?

//////  ENTITY MODELS

public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual Address Address { get; set; }
}

public class Address
{
public int Id { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}

////// VIEW MODEL

public class PersonViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int PersonId { get; set; }
public int AddressId { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}

////// CUSTOM INJECTOR
public class EntityToViewModel : ConventionInjection
{

protected override bool Match(ConventionInfo c)
{
//ignore int = 0 and DateTime = to 1/01/0001
if (c.SourceProp.Type == typeof(DateTime) && (DateTime)c.SourceProp.Value == default(DateTime) ||
(c.SourceProp.Type == typeof(int) && (int)c.SourceProp.Value == default(int)))
return false;

if (c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null)
return true;

if (c.SourceProp.Type == typeof(int) &&
c.TargetProp.Type == typeof(int) )
{
if( "id".Equals(c.SourceProp.Name.ToLower()) &&
c.TargetProp.Name.ToLower().EndsWith("id") &&
c.TargetProp.Name.StartsWith(c.Source.Type.Name))
return true;
}

//Transition logic to SetValue for value types. This should
//allow Address values on Person to be set.
if (!c.SourceProp.Type.IsPrimitive || c.SourceProp.Type.Equals(typeof(string)))
return true;

return false;

//put id logic matching here
//return c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null;
}

protected override object SetValue(ConventionInfo c)
{
//If type is primative or string return the value as is
if (c.SourceProp.Type.IsPrimitive || c.SourceProp.Type.Equals(typeof(string)))
return c.SourceProp.Value;

Object result = Activator.CreateInstance(c.SourceProp.Type)
.InjectFrom<CloneInjection>(c.SourceProp.Value);

//for simple object types create a new instace and apply the clone injection on it
return result;
}
}

////// Program.cs
public class Program
{

public static void Main(string[] args)
{
Person defaultPerson = getDefaultPerson();
//Throws an error. I'm not sure where in the pipeline this occurs, but
//it seems to happen somewhere other than the Match & SetValue method of
//my EntityToViewModel injection
PersonViewModel pvm = CreateFromEntity(defaultPerson);

//Works, but want it more generic & without having to
//include hardcoded prefix for every non-simple object on my EF Model
pvm = CreateFromEntityWorking(defaultPerson);
Console.ReadLine();
}

private static PersonViewModel CreateFromEntity(Person person)
{
PersonViewModel pvm = new PersonViewModel();
pvm.InjectFrom<EntityToViewModel>(person);
return pvm;
}

///WORKING MAPPING BUT SEEMS TOO HARDCODED
private static PersonViewModel CreateFromEntityWorking(Person person)
{
PersonViewModel personvm = new PersonViewModel();

//Fill out view model properties with the same name as those on Person
personvm.InjectFrom(new LoopValueInjection().TargetPrefix("Person"), person);

if (person != null && person.Address != null)
{
//Fill out view model properties for the Address
personvm.InjectFrom(new LoopValueInjection().TargetPrefix("Address"), person.Address);
}

return personvm;
}

public static Person getDefaultPerson()
{
Person p = new Person();
Address a = new Address();
p.Id = 1;
p.FirstName = "John";
p.LastName = "McClain";
a.City = "New York";
a.State = "New York";
a.Zip = "55555";
a.Id = 2;
p.Address = a;
return p;
}

}

最佳答案

终于找到了我需要的例子。可悲的是,尽管我一直在寻找我才刚刚登陆这些。这不是我自己的错;但是,我的脚因为一直在踢它而感到酸痛。

相关网址:

文档 (RTFM) http://valueinjecter.codeplex.com/documentation

扁平化示例和约定 http://valueinjecter.codeplex.com/wikipage?title=flattening&referringTitle=Documentation

Unflattening 示例和约定 http://valueinjecter.codeplex.com/wikipage?title=unflattening&referringTitle=Documentation

我的问题的解决方案:

必须在 View 模型上使用的约定是顶级属性是没有以它们的属性名称为前缀,因为它存在于实体中。因此,在我下面的类中,FirstName、LastName 和 Id 都作为我的 Person 实体的顶级属性存在,它们在我的 View 模型类中没有前缀。 Person.Address 属性的城市、州、邮政编码和 ID 确实有前缀。

奇怪的是,我在尝试实现自己的注入(inject)时想到了这个解决方案。我得到了一个从 Entity 到 ViewModel 的工作......只是不是相反。

public class PersonViewModelPrefixed
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Id { get; set; }
public int AddressId { get; set; }
public string AddressCity { get; set; }
public string AddressState { get; set; }
public string AddressZip { get; set; }
}

public static void Main(string[] args)
{
Person defaultPerson = getDefaultPerson();
PersonViewModelPrefixed defaultPrefixedVm = getDefaultPrefixedViewModel();

//flatten - Entity to View Model
PersonViewModelPrefixed pvm = Flatten(defaultPerson);

//unflatten - View Model to Entity
Person person2 = Unflatten(defaultPrefixedVm);
Console.ReadLine();
}

//unflatten - View Model to Entity
private static Person Unflatten(PersonViewModelPrefixed personViewModel)
{
Person p = new Person();
p.InjectFrom<UnflatLoopValueInjection>(personViewModel);
return p;
}

//flatten - Entity to View Model
private static PersonViewModelPrefixed Flatten(Person person)
{
PersonViewModelPrefixed pvm = new PersonViewModelPrefixed();
pvm.InjectFrom<FlatLoopValueInjection>(person);
return pvm;
}

那么,鉴于这些细节,是否有人对如何使 Flatten 和 Unflatten 方法更通用有一些建议?这就是我接下来要做的。

关于c# - 如何创建自定义值注入(inject)以将我的实体映射到我的 View 模型?包括尝试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12824836/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com