Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将动态代理转换为POCO?_C#_Asp.net Mvc 3_Serialization_Entity Framework 4.1_Dynamic Proxy - Fatal编程技术网

C# 如何将动态代理转换为POCO?

C# 如何将动态代理转换为POCO?,c#,asp.net-mvc-3,serialization,entity-framework-4.1,dynamic-proxy,C#,Asp.net Mvc 3,Serialization,Entity Framework 4.1,Dynamic Proxy,我试图序列化一个域模型,但遇到了一个问题,需要将动态代理转换为POCO。我遇到的问题是,循环引用通过模型中的虚拟属性存在。虽然我试图使用[ScriptIgnore]使序列化程序不解析这些属性,但它仍然会解析这些属性。我认为这是因为对象是动态代理,并且属性中仍然存在一些导致解析器进入的残余(这反过来会导致递归错误“循环引用”-我尝试将递归限制为3个步骤,但我得到了一个错误“超过递归步骤”) 如何将对象从动态代理转换为POCO,以便可以序列化 编辑:简单示例 public class One : B

我试图序列化一个域模型,但遇到了一个问题,需要将动态代理转换为POCO。我遇到的问题是,循环引用通过模型中的虚拟属性存在。虽然我试图使用
[ScriptIgnore]
使序列化程序不解析这些属性,但它仍然会解析这些属性。我认为这是因为对象是动态代理,并且属性中仍然存在一些导致解析器进入的残余(这反过来会导致递归错误“循环引用”-我尝试将递归限制为3个步骤,但我得到了一个错误“超过递归步骤”)

如何将对象从动态代理转换为POCO,以便可以序列化

编辑:简单示例

public class One : BaseViewModel
{
    public int OneId { get; set; }
    public virtual ICollection<Two> Two { get; set; }
}

public class Two
{
    public int TwoId { get; set; }
    public int OneId { get; set; }
    [ScriptIgnore]
    public virtual One One { get; set; }
}

public abstract class BaseViewModel
{
    public string AsJson()
    {
        var serializer = new JavaScriptSerializer();
        return serializer.Serialize(this);
    }
}
公共类一:BaseViewModel
{
public int OneId{get;set;}
公共虚拟ICollection二{get;set;}
}
公共二班
{
public int TwoId{get;set;}
public int OneId{get;set;}
[脚本忽略]
公共虚拟一{get;set;}
}
公共抽象类BaseViewModel
{
公共字符串AsJson()
{
var serializer=新的JavaScriptSerializer();
返回序列化程序。序列化(此);
}
}
这是一个已知的问题

我们修复了ScriptIgnoreAttribute中的一个问题,该问题没有传播到派生类。由于POCO代理类型是通过从用户提供的POCO类派生而创建的,因此JavaScriptSerializer无法看到复制中的[ScriptIgnore]属性

下一个.NET 4.5预览版本中将不包括该修复程序

(因此,您可能需要等待以下预览版本或最终版本)

这在.NET4.5中是固定的


从对该问题的评论来看,如果您使用的是当前版本的JSON.Net,那么您似乎可以使用NonSerializedAttribute而不是ScriptIgnoreAttribute来解决这个问题。Travis,我知道您在这里得到了公认的答案,但我想在这一点上传递一点横向思考。我最近遇到了一个非常类似的问题,我找不到任何适合我的东西,尝试了所有的[scriptignore]装束等等

最终对我有用的是使用Automapper并创建一个从代理对象到精简的poco对象的映射。这在2分钟内解决了我所有的问题。这一切都是在36小时的围攻之后发生的。在试图让代理人打球时,精神状态占了上风——嘘:——)

另一个需要考虑的过渡方法

[编辑]-使用Automapper(这是一个引用Automapper的小测试应用程序)

参考:

nuget:安装包自动映射器

课程:

public sealed class One : BaseViewModel
{
    // init collection in ctor as not using EF in test
    // no requirement in real app
    public One()
    {
        Two = new Collection<Two>();
    }
    public int OneId { get; set; }
    public ICollection<Two> Two { get; set; }
}

public class Two
{
    public int TwoId { get; set; }
    public int OneId { get; set; }
    [ScriptIgnore]
    public virtual One One { get; set; }
}

public abstract class BaseViewModel
{
    public string AsJson()
    {
        var serializer = new JavaScriptSerializer();
        return serializer.Serialize(this);
    }
}

public class OnePoco  : BaseViewModel
{
    public int OneId { get; set; }
    public virtual ICollection<TwoPoco> Two { get; set; }
}

public class TwoPoco
{
    public int TwoId { get; set; }
    public int OneId { get; set; }
}
公共密封一级:BaseViewModel
{
//在测试中未使用EF时初始化ctor中的集合
//在real app中没有要求
公共一号
{
二=新集合();
}
public int OneId{get;set;}
公共ICollection二{get;set;}
}
公共二班
{
public int TwoId{get;set;}
public int OneId{get;set;}
[脚本忽略]
公共虚拟一{get;set;}
}
公共抽象类BaseViewModel
{
公共字符串AsJson()
{
var serializer=新的JavaScriptSerializer();
返回序列化程序。序列化(此);
}
}
公共类OnePoco:BaseViewModel
{
public int OneId{get;set;}
公共虚拟ICollection二{get;set;}
}
公共类TwoPoco
{
public int TwoId{get;set;}
public int OneId{get;set;}
}
测试控制器代码:

public ActionResult Index()
{
    // pretend this is your base proxy object
    One oneProxy = new One { OneId = 1 };
    // add a few collection items
    oneProxy.Two.Add(new Two() { OneId = 1, TwoId = 1, One = oneProxy});
    oneProxy.Two.Add(new Two() { OneId = 1, TwoId = 2, One = oneProxy});

    // create a mapping (this should go in either global.asax 
    // or in an app_start class)
    AutoMapper.Mapper.CreateMap<One, OnePoco>();
    AutoMapper.Mapper.CreateMap<Two, TwoPoco>();

    // do the mapping- bingo, check out the asjson now
    // i.e. oneMapped.AsJson
    var oneMapped = AutoMapper.Mapper.Map<One, OnePoco>(oneProxy);

    return View(oneMapped);
}
public ActionResult Index()
{
//假设这是您的基本代理对象
一个oneProxy=newone{OneId=1};
//添加一些集合项目
Add(newtwo(){OneId=1,TwoId=1,One=oneProxy});
Add(newtwo(){OneId=1,TwoId=2,One=oneProxy});
//创建一个映射(应该放在global.asax中
//或在应用程序中(启动类)
AutoMapper.Mapper.CreateMap();
AutoMapper.Mapper.CreateMap();
//做映射-宾果,现在检查asjson
//即oneMapped.AsJson
var oneMapped=AutoMapper.Mapper.Map(oneProxy);
返回视图(oneMapped);
}

试一试,看看你的进展如何,这对我来说确实有效,“地球”移动了:)

作为Jim的Automapper解决方案的替代方案,我已经成功地将POCO代理“映射”(浅拷贝)到同一POCO的实例。执行此操作的简单方法是修改生成POCO的模板文件,使其包含ToSerializable()方法,因此POCO类如下所示:

public partial class cfgCountry
    {
        public cfgCountry()
        {
            this.People = new HashSet<Person>();
        }

        [Key]
        public int CountryID { get; set; }
        public string Name { get; set; }
        public int Ordinal { get; set; }

        public virtual ICollection<Person> People { get; set; }

        public cfgCountry ToSerializable()
        {
            return new cfgCountry()
            {
            CountryID = this.CountryID,
            Name = this.Name,
            Ordinal = this.Ordinal,
            };
        }
    }
公共部分类cfgCountry
{
公共CFG国家()
{
this.People=newhashset();
}
[关键]
public int CountryID{get;set;}
公共字符串名称{get;set;}
公共整数序号{get;set;}
公共虚拟ICollection人员{get;set;}
公共CFG国家可串行化()
{
返回新的cfgCountry()
{
CountryID=this.CountryID,
Name=this.Name,
序数=这个。序数,
};
}
}
下面是我添加到POCO模板(tt)文件中的函数,用于创建ToSerializable函数(如此难看的语法):


公共可串行化()
{
返回新的()
{
=这个。,
};
}

这并不完美,因为每当您希望序列化结果时,您需要记住返回foo.ToSerializable(),而不是foo本身,但我希望它对某些人有用。

代理是它们所代表的POCO的一个子类。通常,您应该能够很好地序列化它们。你能发布一个你无法序列化的类的小而完整的例子吗?@EricJ。-正常构造时,该类将序列化。我可以发布一个例子,但我不确定它会有多大帮助,因为
<#+
void WriteToSerializableMethod (CodeGenerationTools code, IEnumerable<EdmProperty> primitiveProperties, EntityType entity)
{

#>
public <#=code.Escape(entity)#> ToSerializable()
{
    return new <#=code.Escape(entity)#>()
    {
<#+
    foreach(var edmProperty in primitiveProperties)
    {
#>
    <#=edmProperty.Name#> = this.<#=edmProperty.Name#>,
<#+
    }
#>
    };
}
<#+
}
#>