簡體   English   中英

C#ASP.Net MVC動態對象屬性

[英]C# ASP.Net MVC dynamic object properties

我正在使用C#EF代碼進行ASP.NET MVC項目。

我需要向實體添加動態屬性。 例如 -

我以汽車為基礎。 我可以為其添加自定義屬性,例如引擎功率,長度,顏色等。

屬性可以是布爾值,整數,字符串或選擇選項(即,當用戶輸入這些屬性的值時,我必須創建復選框,輸入或選擇html元素)。

屬性必須具有自定義驗證規則(即,必填,僅數字,僅范圍等)。

你們能給我任何線索或指導來實現這一目標嗎?

謝謝

如果您確實具有動態屬性,則由於EF6假定有關系數據庫,因此您將無法(直接)使用EF6進行此操作。 關系數據庫需要知道期望哪些列。

現在,您有2個選擇。

選項1:將非關系數據庫與EF 7結合使用。您可以在https://msdn.microsoft.com/en-us/magazine/dn890367.aspx上找到有關EF7的更多詳細信息,但基本上在非關系數據庫中,您可以存儲任何json blob-動態屬性也存儲

選項2:在對象中使用鍵值對。 並存儲這些屬性

class KeyValuePair {
   int Id {get; set;}
   string name {get; set;}
   string stringValue {get; set;}

}

class BaseObject {

    int Id {get; set;}
    list<KeyValuePair> dynamicProperties {get; set;}

}

現在,您的汽車可以從該基礎對象繼承。 您仍然需要完成創建KeyValuePair對象的工作。 (如果要存儲字符串,整數等,則可以設置不同的KeyValuePair類型,每種存儲類型都可以使用一種)

但是,如果您使用這樣的動態屬性,請小心性能。

更新:

如果要驗證這樣的動態對象,則要實現IValidatableObject

所以你得到

 class Car: BaseObject, IValidatableObject {
      public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
        /* code to validate your properties here, for example you need at least 1 engine, 4 wheels etc */

        yield return ValidationResult.Success;
    }
 }

您可以在DB中動態創建和使用表,盡管並非如此簡單。

首先,您需要存儲有關表的元數據-它們的名稱是什么,它們具有的屬性是什么,這些屬性的類型是什么,等等。

其次,您將需要生成實體來訪問這些表以及EntityTypeConfiguration類,如下所示:

public class Foo
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class FooTypeConfiguration : EntityTypeConfiguration<Foo>
{
    public FooTypeConfiguration()
    {
        ToTable("Foos");
        HasKey(t => t.Id);
        Property(t => t.Name).HasMaxLength(200)
                             .IsRequired();
    }
}

您可以借助System.Reflection.Emit動態生成DLL,而無需中間的C#代碼。 或者,您可以生成C#代碼並使用System.CodeDom.Compiler進行編譯(這種方式更簡單)。 您也可以嘗試使用Roslyn編譯器(但是我沒有足夠的經驗來推薦它)。

第三,您需要使用modelBuilder.Configurations.AddFromAssembly(...)加載已編譯的DLL並創建DbContext

您可以在程序集中找到所需的類型並使用它來訪問數據:

string typeName = ...;
var type = dynamicLoadedAssembly.GetType(typeName);
var set = dbContext.Set(type); // non-generic DB Set

您可以使用System.Reflectiondynamic類型來處理這些對象。 最后,如果要生成C#代碼,則可以生成屬性和某些接口的實現,以按名稱訪問這些屬性:

public interface IAccessorByName : IReadOnlyDictionary<string, object>
{
    object this[string name] { get; set; }
}

public Foo : IAccessorByName
{
    private static readonly IDictionary<string, Func<Foo, object>> getters = new Dictionary<string, Func<Foo, object>>
    {
        { "Id", (foo) => foo.Id },
        { "Name", (foo) => foo.Name },
    };

    private static readonly IDictionary<string, Action<Foo, object>> setters = new Dictionary<string, Action<Foo, object>>
    {
        { "Id", (foo, value) => { foo.Id = (int)value; } },
        { "Name", (foo, value) => { foo.Name = (string)value; } },
    };

    public int Id { get; set; }

    public string Name { get; set; }

    public object this[string name]
    {
       get { return getters[name](this); }
       set { setters[name](this, value); }
    }
}

使用類似的界面,您可以動態創建,讀取,更新和刪除對象:

string typeName = "Foo";
var fooType = dynamicLoadedAssembly.GetType(typeName);
var foo = (IAccessorByName)Activator.CreateInstance(fooType);

foo["Id"] = 1;
foo["Name"] = "Jon Skeet";

var fooSet = dbContext.Set(fooType);
fooSet.Add(foo);
dbContext.SaveChanges();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM