C# 寻找模式想法 - 带构造函数的继承问题

标签 c# design-patterns entity-framework-4

我有一个多层应用程序,我正在使用 Entity Framework 4 w/Code First 重写。重要的事情:

在数据层中,在我的上下文中,我有:

public DbSet<MobileSerialContainer> Mobiles { get; set; }

此上下文有一个静态实例。我知道,我知道,这种做法很糟糕。我这样做的原因与本文无关。

MobileSerialContainer 包含以下内容:

[Table("Mobiles")]
public sealed class MobileSerialContainer
{
    [Key]
    public long Serial { get; set; }

    [StringLength(32)]
    public string Name { get; set; }

    public MobileSerialContainer() { }

    public MobileSerialContainer(Mobile mobile)
    {
        Mobile = mobile;
        LeContext.Instance.Mobiles.Add(this);
    }

    [StringLength(1024)]
    public string FullClassName
    {
        get { return Mobile == null ? "" : Mobile.GetType().AssemblyQualifiedName; }
        set
        {
            if (string.IsNullOrEmpty(value) || value == FullClassName)
                return;

            Mobile = null;

            var type = Type.GetType(value);
            if (type == null)
                return;

            if (!type.IsSubclassOf(typeof(Mobile))
                && type != typeof(Mobile))
                return;

            var constructor = type.GetConstructor(new [] { GetType() });

            // The problem here is that Person ( which extends mobile ) does not have a constructor that takes a MobileSerialContainer.
            // This is a problem of course, because I want to make this entire layer transparent to the system, so that each derivative
            // of Mobile does not have to implement this second constructor. Blasphemy!

            if (constructor == null)
                return;

            Mobile = (Mobile)constructor.Invoke(new object[] { this });
        }
    }

    public string SerializedString
    {
        get
        {
            return Mobile == null ? "" : Mobile.Serialize();
        }
        set
        {
            if (Mobile == null)
                return;

            if (string.IsNullOrEmpty(value))
                return;

            Mobile.Deserialize(value);
        }
    }

    [NotMapped]
    public Mobile Mobile { get; set; }

    public void Delete()
    {
        LeContext.Instance.Mobiles.Remove(this);
    }
}

现在...我知道这是一篇很长的文章。手机是这样的:

public class Mobile
{
    public long Serial { get { return Container.Serial; } }

    public string Name { get { return Container.Name; } set { Container.Name = value; } }

    public Mobile()
    {
        Container = new MobileSerialContainer(this);
    }

    public Mobile(MobileSerialContainer container)
    {
        Container = container;
    }

    public void Delete()
    {
        Container.Delete();
    }

    private MobileSerialContainer Container { get; set; }

    protected static string MakeSafeString(string value)
    {
        if (string.IsNullOrEmpty(value))
            return value;

        return value.Replace("&", "&amp;")
                    .Replace(",", "&comma;")
                    .Replace("=", "&eq;");
    }

    protected static string MakeUnsafeString(string value)
    {
        if (string.IsNullOrEmpty(value))
            return value;

        return value.Replace("&eq;", "=")
                    .Replace("&comma;", ",")
                    .Replace("&amp;", "&");
    }

    public virtual string Serialize()
    {
        string result = "";

        var properties = PersistentProperties;

        foreach (var property in properties)
        {
            string name = MakeSafeString(property.Name);
            var value = property.GetValue(this, null);
            string unsafeValueString = (string)Convert.ChangeType(value, typeof(string));
            string valueString = MakeSafeString(unsafeValueString);
            result += name + "=" + valueString + ",";
        }

        return result;
    }

    public virtual void Deserialize(string serialized)
    {
        var properties = PersistentProperties.ToList();
        var entries = serialized.Split(',');
        foreach (var entry in entries)
        {
            if (string.IsNullOrEmpty(entry))
                continue;

            var keyPair = entry.Split('=');
            if (keyPair.Length != 2)
                continue;

            string name = MakeUnsafeString(keyPair[0]);
            string value = MakeUnsafeString(keyPair[1]);

            var property = properties.FirstOrDefault(p => p.Name == name);
            if (property == null)
                continue;

            object rawValue = Convert.ChangeType(value, property.PropertyType);
            property.SetValue(this, rawValue, null);
        }
    }

    protected IEnumerable<PropertyInfo> PersistentProperties
    {
        get
        {
            var type = GetType();
            var properties = type.GetProperties().Where(p => p.GetCustomAttributes(typeof(PersistAttribute), true).Any());

            return properties;
        }
    }
}

在此之上的几层,我有系统层,其中有 Person 类:

public class Person : Mobile
{
    [Persist]
    public string LastName { get; set; }
}

基本思想是这样的:我希望系统层几乎不了解数据层。它创建任何扩展“Mobile”的内容,并自动保存到数据库中。我不想为 Person 建立一个表,因此需要奇怪的序列化内容,因为实际上有数百个扩展 Mobile 的类。我不想要数百张 table 。所有这些序列化的东西都工作得很好,SerializedString 位,保存所有内容,重新加载等等。我唯一没有想出解决方案的是:

我不想为 Person 实现两个构造函数:

public Person() : base() { }

public Person(MobileSerialContainer container)
    : base(container) { }

因为这需要系统层对数据层有更多的了解。

奇怪的序列化字符串仍然存在。反射业务仍然存在。我知道它很慢,但是数据库写入和读取非常罕见,而且无论如何都是异步的。

除此之外,我正在寻找有关如何解决此问题的任何好主意。谢谢!

[编辑] 更改了此处粘贴的 MobileSerialContainer 类中写错的代码行。

最佳答案

如果您正在重写应用程序,您可以重新考虑系统的所有设计,以保持域层(系统层)独立于数据访问层,使用:

  • 用于处理对数据库 (dataContext) 的访问的存储库模式
  • 业务对象(移动设备等)的域层
  • 控制反转模式 (IOC),使各层保持松散耦合

继承的东西绝对不是保持系统松散耦合的好方法。

关于C# 寻找模式想法 - 带构造函数的继承问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16633405/

相关文章:

c# - 关闭传输错误。等待客户端数据超时

c# - 使用哪种模式进行日志记录?依赖注入(inject)还是服务定位器?

c# - 如何将 C# Select () 扩展委托(delegate)或表达式传递给存储库?

c# - 将 app.config 作为 MSBuild 脚本的一部分进行更改

c# - DepencyProperty 未通过 UserControl 上的绑定(bind)进行更新

android - Android中MVP设计架构中Presenter是否应该处理View的所有事件?

wcf - 企业解决方案中的 Entity Framework

c# - 如何防止 Entity Framework 强制验证子对象属性?

c# - 存储库模式和多个相关的核心实体或业务对象——一个存储库还是多个?

c# - 类接口(interface)应该放在 .NET 类库中的什么位置?