Xamarin 表单和 EntityFramework 属性兼容性

Posted

技术标签:

【中文标题】Xamarin 表单和 EntityFramework 属性兼容性【英文标题】:Xamarin Forms and EntityFramework Attributes compatibility 【发布时间】:2017-09-01 02:10:29 【问题描述】:

我有一个使用C#WPFASP.NET WebAPIEntity Framework客户端/服务器解决方案。客户端和服务器类在他的项目之间共享模型。现在我正在尝试创建一个新客户端,使用 Xamarin 表单并将模型共享给,但 Entity Framework 属性MaxLengthIndexNotMapped 等)是 在 PCL 中不兼容。所以这是我尝试过的事情:

将 Microsoft.EntityFrameworkCore 导入 PCL 模型

如here 所述,您应该能够将实体框架与 Xamarin 表单一起使用,因此我将 PCL 转换为 NetStandard 1.3,并且它可以工作,每个 EntityFramework 属性都是允许的。但是现在服务器项目不兼容那个标准,我不能在模型项目中添加像prism和Newtonsoft.Json这样的包。

使用诱饵和切换技巧模拟 Xamarin 表单的属性

我已经尝试了here 中描述的方法,基于在模型 PCL 中创建自定义属性,并在类库中重新定义它们。 MyClient.Droid 和 MyClient.UWP 重新定义属性,将它们留空,MyServer 将使用实体框架功能重新定义它们。

自定义 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; 

我目前还没有完全部署这种方法,但如果我不能让前两种方法都起作用,我会继续这样做。

编辑 - 尝试使“诱饵和切换属性”方法起作用

正如@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根据调用程序集选择自定义属性或EF属性的机制是什么。

我还在我的服务器项目中添加了一个名为 TypeForwarding.Net.cs(建议 here)的文件,其中包含:

[assembly: TypeForwardedTo(typeof(IndexAttribute))]

但还是不行。

【问题讨论】:

诱饵和转换技术有什么问题。有什么不适合你吗?这是解决此问题的最干净的解决方案。 @AdamPedley 问题是我无法让它工作。正如我所说,当我从服务器端的类创建 Model.Compatibility.IndexAttribute 的实例时,不会调用 MockedAttribute 构造函数,因此它不起作用。我应该做错了什么,你能告诉我一个应用诱饵和切换技术重新定义属性的例子吗? 属性构造函数只会在实际获取该模型的属性并尝试读取它们时运行。它不一定会在您调用它时运行。通过调用 typeof(MyModel).GetCustomAttributes(true); 对其进行测试在实际附加了属性的模型上。 好吧,我想我理解你了。我应该只在没有它的项目中重新定义模拟属性。我不明白的部分是:如何在不同的程序集中正确定义它的项目(安装了 EntityFramework 的服务器项目)? System.ComponentModel.DataAnnotations.Schema.IndexAttribute vs Model.Compatibility.Attribute,是不是有冲突?或者它只是优先考虑系统一? 我相信 EF fluent API 是 PCL 和 NetStandard 友好的。因此,您可以创建 POCO 对象并让 fluent api 进行跨平台映射,而不是使用属性。 msdn.microsoft.com/en-us/library/jj591617(v=vs.113).aspx(注意:我使用 EF6 和 PCL 项目在 MVC / WPF / Mobile 之间共享项目) 【参考方案1】:

我相信 EF fluent API 是 PCL 和 NetStandard 友好的。因此,您可以创建 POCO 对象并让 fluent api 进行跨平台映射,而不是使用属性。 msdn.microsoft.com/en-us/library/jj591617(v=vs.113).aspx

注意:我使用 EF6 和 PCL 项目在 MVC/WPF/Mobile 之间共享的项目中做到了这一点

【讨论】:

如果您为 OP 共享该内核会很好。 什么核心?如果您的意思是代码,文档中有足够的示例或在 Google 上搜索。遗憾的是,我无法共享代码,因为该项目是几年前的一份工作。

以上是关于Xamarin 表单和 EntityFramework 属性兼容性的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin:用于 Android 和 Windows UWP 的 Xamarin 表单中的分组列表的垂直字母索引(跳转列表)

Xamarin 表单 TabbedPage

Xamarin 表单和 EntityFramework 属性兼容性

Xamarin 服务和表单初始化

在 Xamarin 表单中使用带有图像和文本的按钮

Xamarin 表单的 ANPR