Xamarin Forms 和 EntityFramework 属性兼容性
Xamarin Forms and EntityFramework Attributes compatibility
我有一个 client/server 解决方案 使用 C#
、WPF
、ASP.NET WebAPI
和 Entity Framework
。客户端和服务器类 在他的项目中共享模型。现在我正在尝试创建一个新客户端,使用 Xamarin Forms 并将模型共享给,但是 Entity Framework attributes(MaxLength
, Index
, NotMapped
, 等等) 在 PCL 中不兼容。所以这是我尝试过的事情:
导入 Microsoft.EntityFrameworkCore 到 PCL 模型
如 here 所述,您应该能够将 entity framework 与 Xamarin 表单一起使用,因此我将 PCL 转换为 NetStandard 1.3,它可以正常工作,每个 EntityFramework 属性是允许的。但是现在服务器项目与该标准不兼容,我无法在模型项目中添加棱镜和 Newtonsoft.Json 等包。
使用诱饵和切换技巧模拟 Xamarin 表单的属性
我已经尝试过 here 中描述的方法,基于在模型 PCL 中创建自定义属性,并在 class 库中重新定义它们。 MyClient.Droid 和 MyClient.UWP 重新定义属性,将它们留空,MyServer 将使用 Entity Framework 功能重新定义它们。
自定义 IndexAttribute - 模型 PCL:
namespace Model.Compatibility
{
public class IndexAttribute : Attribute
{
public IndexAttribute()
{
}
}
}
自定义 IndexAttribute - 服务器端:
[assembly: TypeForwardedToAttribute(typeof(Model.Compatibility.IndexAttribute))]
namespace Model.Compatibility
{
public class MockedIndexAttribute : System.ComponentModel.DataAnnotations.Schema.IndexAttribute
{
public MockedIndexAttribute()
{
}
}
}
我测试了这个调用 var attribute = new Model.Compatibility.IndexAttribute();
的方法。永远不会调用 MockedIndexAttribute 构造函数。
创建共享项目而不是 PCL
这种方式有点乱,但看起来可行。只需为模型创建一个新的共享项目,并使用如下条件标志:
#if !__MOBILE__
[NotMapped, Index]
#endif
public Guid Id { get; set; }
目前我还没有完全部署这种方法,但是如果我无法使前两种方法中的 none 起作用,我将采用这种方法。
编辑 - 尝试使 "Bait and Switch Attributes" 方法起作用
正如@AdamPedley 所建议的那样,this 线程,我在新的 PCL(Xamarin.Compatibility) 中重新定义了 IndexAttribute,使用与原始命名空间相同的命名空间:
namespace System.ComponentModel.DataAnnotations.Schema
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class IndexAttribute : Attribute
{
public IndexAttribute() { }
}
}
现在,我的 PCL 模型包含对 Xamarin.Compatibility 的引用,因此我可以在我的模型属性中使用 Index 属性:
[Index]
public Guid Id { get; set; }
然后,从我的服务器项目中,我调用下一行代码来检查调用的构造函数、自定义属性或由 EntityFramework:
定义的构造函数
PropertyInfo prop = typeof(MyClass).GetProperty("Id");
object[] attributes = prop.GetCustomAttributes(true);
调用的构造函数是自定义的,所以它不起作用,因为它必须调用EntityFramework定义的属性。那是我不知道的事情,根据调用程序集使我的模型的 PCL select 自定义属性或 EF 属性的机制是什么。
我还在我的服务器项目中添加了一个文件,名为 TypeForwarding.Net.cs(如建议 here),其中包含:
[assembly: TypeForwardedTo(typeof(IndexAttribute))]
但还是不行。
我相信 EF fluent API PCL 和 NetStandard 友好。因此,您可以创建 POCO 对象并让流利的 api 进行跨平台映射,而不是使用属性。 msdn.microsoft.com/en-us/library/jj591617(v=vs.113).aspx
注意:我在一个使用 EF6 的项目和 PCL 跨 MVC/WPF/Mobile 共享的项目中做到了这一点
我有一个 client/server 解决方案 使用 C#
、WPF
、ASP.NET WebAPI
和 Entity Framework
。客户端和服务器类 在他的项目中共享模型。现在我正在尝试创建一个新客户端,使用 Xamarin Forms 并将模型共享给,但是 Entity Framework attributes(MaxLength
, Index
, NotMapped
, 等等) 在 PCL 中不兼容。所以这是我尝试过的事情:
导入 Microsoft.EntityFrameworkCore 到 PCL 模型
如 here 所述,您应该能够将 entity framework 与 Xamarin 表单一起使用,因此我将 PCL 转换为 NetStandard 1.3,它可以正常工作,每个 EntityFramework 属性是允许的。但是现在服务器项目与该标准不兼容,我无法在模型项目中添加棱镜和 Newtonsoft.Json 等包。
使用诱饵和切换技巧模拟 Xamarin 表单的属性
我已经尝试过 here 中描述的方法,基于在模型 PCL 中创建自定义属性,并在 class 库中重新定义它们。 MyClient.Droid 和 MyClient.UWP 重新定义属性,将它们留空,MyServer 将使用 Entity Framework 功能重新定义它们。
自定义 IndexAttribute - 模型 PCL:
namespace Model.Compatibility
{
public class IndexAttribute : Attribute
{
public IndexAttribute()
{
}
}
}
自定义 IndexAttribute - 服务器端:
[assembly: TypeForwardedToAttribute(typeof(Model.Compatibility.IndexAttribute))]
namespace Model.Compatibility
{
public class MockedIndexAttribute : System.ComponentModel.DataAnnotations.Schema.IndexAttribute
{
public MockedIndexAttribute()
{
}
}
}
我测试了这个调用 var attribute = new Model.Compatibility.IndexAttribute();
的方法。永远不会调用 MockedIndexAttribute 构造函数。
创建共享项目而不是 PCL
这种方式有点乱,但看起来可行。只需为模型创建一个新的共享项目,并使用如下条件标志:
#if !__MOBILE__
[NotMapped, Index]
#endif
public Guid Id { get; set; }
目前我还没有完全部署这种方法,但是如果我无法使前两种方法中的 none 起作用,我将采用这种方法。
编辑 - 尝试使 "Bait and Switch Attributes" 方法起作用
正如@AdamPedley 所建议的那样,this 线程,我在新的 PCL(Xamarin.Compatibility) 中重新定义了 IndexAttribute,使用与原始命名空间相同的命名空间:
namespace System.ComponentModel.DataAnnotations.Schema
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class IndexAttribute : Attribute
{
public IndexAttribute() { }
}
}
现在,我的 PCL 模型包含对 Xamarin.Compatibility 的引用,因此我可以在我的模型属性中使用 Index 属性:
[Index]
public Guid Id { get; set; }
然后,从我的服务器项目中,我调用下一行代码来检查调用的构造函数、自定义属性或由 EntityFramework:
定义的构造函数PropertyInfo prop = typeof(MyClass).GetProperty("Id");
object[] attributes = prop.GetCustomAttributes(true);
调用的构造函数是自定义的,所以它不起作用,因为它必须调用EntityFramework定义的属性。那是我不知道的事情,根据调用程序集使我的模型的 PCL select 自定义属性或 EF 属性的机制是什么。
我还在我的服务器项目中添加了一个文件,名为 TypeForwarding.Net.cs(如建议 here),其中包含:
[assembly: TypeForwardedTo(typeof(IndexAttribute))]
但还是不行。
我相信 EF fluent API PCL 和 NetStandard 友好。因此,您可以创建 POCO 对象并让流利的 api 进行跨平台映射,而不是使用属性。 msdn.microsoft.com/en-us/library/jj591617(v=vs.113).aspx
注意:我在一个使用 EF6 的项目和 PCL 跨 MVC/WPF/Mobile 共享的项目中做到了这一点