我有一个使用 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("&", "&")
.Replace(",", ",")
.Replace("=", "&eq;");
}
protected static string MakeUnsafeString(string value)
{
if (string.IsNullOrEmpty(value))
return value;
return value.Replace("&eq;", "=")
.Replace(",", ",")
.Replace("&", "&");
}
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;
}
}
}
在此之上的几层,我有 System 层,其中我有类 Person:
public class Person : Mobile
{
[Persist]
public string LastName { get; set; }
}
基本思想是这样的:我希望 System 层对 Data 层几乎一无所知。它创建任何扩展“Mobile”的东西,这些东西会自动保存到数据库中。我不想为 Person 提供一个表,因此会出现奇怪的序列化内容,因为实际上有数百个类可以扩展 Mobile。我不想要数百张桌子。所有这些序列化的东西都可以完美运行,SerializedString 位,保存所有内容,重新加载等等。我唯一没有想出解决方案的是:
我不想为 Person 实现两个构造函数:
public Person() : base() { }
public Person(MobileSerialContainer container)
: base(container) { }
因为这需要系统层对数据层有更多的了解。
奇怪的序列化字符串仍然存在。反射业务仍然存在。我知道它很慢,但是数据库写入和读取非常罕见,而且无论如何都是异步的。
除此之外,我正在寻找有关如何解决此问题的任何很酷的想法。谢谢!
[编辑] 更改了粘贴在此处的 MobileSerialContainer 类中的错误代码行。