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

これは不可能です。

部分クラスは、基本的に同じクラスの一部です。

メソッドを2回定義したり、オーバーライドしたりすることはできません(コンストラクターにも同じルールが適用されます)

ただし、以下の回避策を使用できます。

//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 に答える
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; } 

}

私が推測する欠点は、生成されたクラスが「クリーン」ではないことです。つまり、complex/nav 型の自動実装プロパティだけを持つことはできません。

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 に答える
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 に答える
0
  1. 基本クラスを追加します。

     public class CallBase
     {
            protected CallBase()
            {
                Initialize();
            }
    
            protected abstract void Initialize();
     }
    
  2. 部分クラスの実装を別のファイルに追加します

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

欠点は、すべてのコレクション クリーチャーの前に Initialization メソッドが呼び出されることです。

于 2013-04-22T08:45:11.330 に答える