Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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# 是否有一种设计模式可以避免这种重复或反射?_C#_Entity Framework_Design Patterns_Reflection - Fatal编程技术网

C# 是否有一种设计模式可以避免这种重复或反射?

C# 是否有一种设计模式可以避免这种重复或反射?,c#,entity-framework,design-patterns,reflection,C#,Entity Framework,Design Patterns,Reflection,情况: 我有一些代码可以是: a) 性能差(反射) b) 重复的 c) 难以维持 我希望有一种方法可以获得可维护的、不重复的代码,而这些代码没有反射所带来的性能影响 a)一个性能清根功能 static public SelectListItem ToSelectListItem(this Object item, string textProperty, string valueProperty, bool isSelected) { return new SelectListIte

情况:

我有一些代码可以是:

  • a) 性能差(反射)
  • b) 重复的
  • c) 难以维持
我希望有一种方法可以获得可维护的、不重复的代码,而这些代码没有反射所带来的性能影响

a)一个性能清根功能

static public SelectListItem ToSelectListItem(this Object item, string textProperty, string valueProperty, bool isSelected)
{
    return new SelectListItem()
    {
        Selected = false,
        Text = item.GetType().GetProperty(textProperty).GetValue(item, null),
        Value = item.GetType().GetProperty(valueProperty).GetValue(item, null)
    };
}
b)12个代码90%相似的函数

static public SelectListItem ToSelectListItem(this Class1 type)
{
    return new SelectListItem()
    {
        Selected = false,
        Text = type.Name,
        Value = type.LoadInfoTypeID.ToString() // This ID is the only thing that changes.
    };
}
c)1需要一些稍微难以维护的编码的功能

static public SelectListItem ToSelectListItem(this Object type)
{
    int ID = type is Class1 ? (type as Class1).SomeID :
             type is Class2 ? (type as Class2).AnotherID :
             type is ClassN ? (type as ClassN).YetAnotherID :
             -1;
    return new SelectListItem()
    {
        Selected = false,
        Text = type.Name, // Ignore the fact that Object doesn't technically have a Name Prop for the moment.
        Value = ID.ToString()
    };
}
问题

是否有一种更易于维护且不重复的方式使上面的代码不会抑制性能(至少不会过度)

情况c)是可以接受的,如果我必须使用它,但我想知道是否有我不知道的任何替代方案

同时


这些类(Class1、Class2等)是实体框架中的实体。我不确定这是否会添加/删除任何可用的选项。

让有问题的类遵守特定的接口,该接口允许根据需要对数据进行通用的操作方式

接口提供了一个契约,未来的程序员可以理解该契约以进行维护,并允许在反射操作之外以类型一致的方式处理实例


似乎有一种模式是可以识别的;因此,使用此设计仅对现有流程有效。辅助接口(?)可以处理其他实例,即其他处理的5%。

我建议将您的类派生自某个基类,该基类将公开一些将被覆盖的
ID
字段或方法
GetId

public abstract class YourAbstractClass 
{
    public abstract int ID { get; set; }
}

public class ConcreteClass1 : YourAbstractClass
{
    public override int ID
    { 
        get { return SomeID } 
        set { SomeID = value } 
    }
}
如果是属性,您可能需要使用
NotMappedAttribute
装饰
ID
,您有一些选择(没有第三方库,比如为您提供此类功能的库)

一种是在类上使用接口,并将其传入(请参阅)

另一个选项是使用一个函数,该函数接受一些委托来决定要使用的类型

static public SelectListItem ToSelectListItem<TItem>(this TItem type, Func<TItem, string> nameSelector, Func<Titem, string> valueSelector)
{

    return new SelectListItem()
    {
        Selected = false,
        Text = nameSelector(type)
        Value = valueSelector(type)
    };
}

//elsewhere
Class1 item1 = ...
item1.ToSelectListItem(a=>a.Name, a=>a.SomeId);
Class2 item2 = ...
item2.ToSelectListItem(a=>a.Name, a=>a.AnotherID);
ClassN itemN = ...
itemN.ToSelectListItem(a=>a.Name, a=>a.YetAnotherID);
static public SelectListItem到SelectListItem(此TItem类型、Func nameSelector、Func valueSelector)
{
返回新的SelectListItem()
{
所选=假,
Text=名称选择器(类型)
值=值选择器(类型)
};
}
//别处
类别1第1项=。。。
item1.ToSelectListItem(a=>a.Name,a=>a.SomeId);
类别2项目2=。。。
item2.ToSelectListItem(a=>a.Name,a=>a.AnotherID);
ClassN itemN=。。。
itemN.ToSelectListItem(a=>a.Name,a=>a.YetAnotherID);

也许一个类似于a)但没有反射的解决方案就足够了?另外,您不必使用字符串名称引用属性

public static SelectListItem<T>(T o, Func<T, string> textFunc, Func<T, string> valueFunc)
{
    return new SelectListItem
        {
            Selected = false,
            Text = textFunc(o),
            Value = valueFunc(o)
        }

}
public static SelectListItem(to,Func textFunc,Func valueFunc)
{
返回新的SelectListItem
{
所选=假,
Text=textFunc(o),
Value=valueFunc(o)
}
}

您也可以在EF生成的代码中添加属性。大多数模板为此目的生成分部。所以你可以:

public interface ITextValue
{
    string GetValue();
    string GetText();
}

// for each entity
public partial class SomeEntity : ITextValue // this for each EF-type
{
    public GetValue() { return this.ID.ToString(); }
    public GetValue() { return this.Name; }
}
然后

static public SelectListItem ToSelectListItem(this ITextValue obj)
{
    return new SelectListItem()
    {
        Selected = false,
        Text = obj.GetText(),
        Value = obj.GetValue()
    };
}
static public SelectListItem ToSelectListItem(this object item)
{
    var reader = Readers(typeof(item));
    return new SelectListItem()
    {
        Selected = false,
        Text = reader.GetText(),
        Value = reader.GetValue()
    };
}
但是,如果您不想修改EF类型,可以使用以下方法:

public interface ITextValue
{
    string GetValue(object obj);
    string GetText(object obj);
}

// for each entity
public class SomeEntityReader : ITextValue // this for each EF-type
{
    public GetValue(object obj) { return ((SomeEntity).ID).ToString(); }
    public GetValue(object obj) { return ((SomeEntity)this).Name; }
}

// somewhere central
var Readers = new Dictionary<Type,ITextValue>()
Readers.Add(typeof(SomeEntity), new SomeEntityReader());
// etc

是否有可能让第三方名称空间或(在我的例子中)实体框架的类遵守我创建的接口?它真的是第三方的,还是EF自动生成的类?如果只是自动生成的类,默认情况下,这些类应该是
partial
,因此您应该能够在同一命名空间中的自己的分部类中添加接口。对于EF情况,为目标实体创建一个分部类,该实体依附于接口,如果需要,提供新属性,该属性只需路由到内部属性即可使用95%情况,好吧。我想我应该问一下EF接口,而不是哈哈。知道这一点会有很大帮助。我只是假设如果你先做数据库是不可能的。@Shelby115我已经做了一段时间的EF部分技巧,所以你在正确的道路上。哦,快!我完全忘了这些东西!我用它!最后我认为在这种情况下,欧米伽曼的答案是最好的,但我真的很感激这个答案。我一直在寻找这样的情况。