10

EF 为我生成了一些部分类,每个类都有一个构造函数,但它说不要碰它们(下面的示例),现在如果我创建自己的次要部分类并且我想要一个构造函数来自动设置一些字段如何我这样做会发生冲突吗?

//------------------------------------------------------------------------------
// <auto-generated>
//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Breakdown.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Call
    {
        public Call()
        {
            this.Logs = new HashSet<Log>();
        }

        ...
    }
}
4

5 回答 5

20

部分方法可以在这里为您提供帮助,在 T4 模板中定义了一个无主体的部分方法并在构造函数中调用它。

public <#=code.Escape(entity)#>()
{
    ...
    OnInit();
}

partial void OnInit();

然后在您的部分类中定义部分方法并将您想要在构造函数中执行的操作放入其中。如果您不想做任何事情,那么您不需要定义部分方法。

partial class Entity()
{
    partial void OnInit()
    {
        //constructor stuff
        ...
    }
}

http://msdn.microsoft.com/en-us/library/vstudio/6b0scde8.aspx

于 2013-05-25T03:19:32.353 回答
1

我最近也想做同样的事情,最后修改了 T4 模板,这样我就可以手动实现自己的无参数构造函数。为此,您可以从生成的类中删除构造函数,并将集合等的实例化移动到构造函数之外,这样:

public Call()
{
  this.Logs = new HashSet<Log>();
}

变成这样:

private ICollection<Log> logs = new HashSet<Log>();
public virtual ICollection<Log> Logs 
{ 
  get { return this.logs; } 
  set { this.logs = value; } 

}

我认为的缺点是生成的类不是“干净”的。也就是说,您不能只为您的复杂/导航类型提供自动实现的属性。

在您的 model.tt 文件中,您可以通过删除以下代码、将其注释掉或仅在条件中放入 false 来阻止构造函数的生成,这样它就永远不会被执行:

if (propertiesWithDefaultValues.Any() || complexProperties.Any())
{
#>
  public <#=code.Escape(complex)#>()
  {
<#
    foreach (var edmProperty in propertiesWithDefaultValues)
    {
#>
      this.<#=code.Escape(edmProperty)#> =
         <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
    }

    foreach (var complexProperty in complexProperties)
    {
#>
      this.<#=code.Escape(complexProperty)#> = new
        <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
    }
#>
  }

然后在下面,您需要进行一些修改,为您的复杂类型和导航类型生成属性。添加一个带有对象实例化的私有 var 和一个用于访问这些私有 var 的属性,例如:

if (complexProperties.Any())
{
  foreach(var complexProperty in complexProperties)
  {
    //generate private var + any instantiation
    //generate property for accessing var
  }
}

根据模型的复杂性,您可能需要修改其他区域。希望这能让你开始。

于 2013-01-23T20:28:02.427 回答
1

这是不可能的。

部分类本质上是同一类的一部分。

没有方法可以被定义两次或被覆盖(同样的规则也适用于构造函数)

但是您可以使用下面提到的解决方法:

//From file SomeClass.cs - generated by the tool
public partial class SomeClass
 {
    // ...
 }


// From file SomeClass.cs - created by me
public partial class SomeClass
  {
    // My new constructor - construct from SomeOtherType
    // Call the default ctor so important initialization can be done
    public SomeClass(SomeOtherType value) : this()
      {

       }
  } 

有关更多信息,请查看部分类、默认构造函数

我希望这对你有帮助。

于 2013-01-23T18:03:20.153 回答
0
  1. 添加一个基类:

     public class CallBase
     {
            protected CallBase()
            {
                Initialize();
            }
    
            protected abstract void Initialize();
     }
    
  2. 在另一个文件中添加部分类实现

     public partial class Call: CallBase
     {
        protected override void Initialize();
        {
       ...
         }
     }
    

缺点是初始化方法会在所有集合生物之前被调用。

于 2013-04-22T08:45:11.330 回答
0

如果我很好理解这个问题,那么在创建一个新实体时需要这个构造函数,这是一个以前没有持久化的实体。

我的情况是为所有日期时间设置一个默认值,即将它们初始化为“时间的开始”:1900-01-01。

在这种情况下,我使用实体工厂

public static T GetNewEntity<T> () {
    T e;
    try {
        e = Activator.CreateInstance<T>();
    } catch {
        e = default(T);
    }
    SetDefaults(e);

    return e;
}

每次我需要一个新实体时,我都会使用

Entity e = GetNewEntity<Entity>();

使用 SetDefaults 为:

public static void SetDefaults (object o) {
    Type T = o.GetType();
    foreach ( MemberInfo m in T.GetProperties() ) {
        PropertyInfo P = T.GetProperty(m.Name);
        switch ( Type.GetTypeCode(P.PropertyType) ) {
            case TypeCode.String :
                if ( P.GetValue(o, null) == null ) 
                    P.SetValue(o, String.Empty, null); 
                break;
            case TypeCode.DateTime :
                if ( (DateTime)P.GetValue(o, null) == DateTime.MinValue )
                    P.SetValue(o, EntityTools.dtDef, null); 
                break;
        }
    }
}

完整代码在这里

它可以被重写以考虑实体类型等等......

于 2014-07-15T08:49:00.317 回答