如何解决跨AppDomain边界代理匿名对象
| 我要为RazorEngine vNext解决的最受要求的功能之一就是支持将模板程序集加载到单独的“ 0”中,因此我们可以在需要时卸载这些程序集。对功能的要求很高,但具有连锁效应,即对可以注入模板的可能模型类型引入约束。 当前v2.1版本的一个不错的功能之一就是能够使用匿名类型作为模型。我们进行确定模板中的模型类型为匿名类型的工作,并将基本模板设置为TemplateBase<dynamic>
。运行时绑定程序为我们照顾了模型成员的后期绑定调用。一切都很好。
当我们在单独的ѭ0中引入对运行模板的支持时,我们现在面临一个约束,即模型只能是[Serializable]
类型(通过继承through4ѭ隐含)。匿名类型不可序列化,并且也是“ 5”。
我的想法是在模板库中以某种方式创建一个代理模型(称为“ 6”),该代理模型将对模型的调用分派(将在调用域中,而不是在模板运行所在的域中)。在本质上:
模板:
<h1>@Model.Name</h1>
呼叫@Model.Name
会执行以下操作:
Template.Model (ModelProxy) -> GetMember(Name) -> |BOUNDARY| -> Model.Name
是否有人知道或具有尝试将呼叫代理到另一个“ 0”中的匿名(或“ 6”对象)的最佳方法的经验或经验?
重要的是,我并没有试图将匿名对象推过“ 0”边界,这是无法做到的。
解决方法
好。假设您了解反射并创建一个新的
AppDomain
。我知道你知道该怎么做... :)
我创建了两个帮助程序类,这些类允许您传递匿名对象。 ProxyAnonymousObject
和ProxyDynamicObject
。您在第一个“ 0”中创建“ 14”,并在另一个“ 0”中使用“ 15”。 (这两个对象都存在于主“ 0”库中)
[Serializable]
public class ProxyAnonymousObject : ISerializable {
static Dictionary<string,Type> cached = new Dictionary<string,Type>();
object model;
public Dictionary<string,object> ModelProperties = new Dictionary<string,object>();
public ProxyAnonymousObject(object model) { this.model = model; }
public ProxyAnonymousObject(SerializationInfo info,StreamingContext ctx) {
try {
string fieldName = string.Empty;
object fieldValue = null;
foreach (var field in info) {
fieldName = field.Name;
fieldValue = field.Value;
if (string.IsNullOrWhiteSpace(fieldName))
continue;
if (fieldValue == null)
continue;
ModelProperties.Add(fieldName,fieldValue);
}
} catch (Exception e) {
var x = e;
}
}
public void GetObjectData(SerializationInfo info,StreamingContext context) {
foreach (var pi in model.GetType().GetProperties()) {
info.AddValue(pi.Name,pi.GetValue(model,null),pi.PropertyType);
}
}
}
public class ProxyDynamicObject : DynamicObject{
internal ProxyAnonymousObject Proxy { get; set; }
public ProxyDynamicObject(ProxyAnonymousObject model) {
this.Proxy = model;
}
public override bool TryGetMember(GetMemberBinder binder,out object result) {
result = Proxy.ModelProperties[binder.Name];
return true;
}
}
为了使它在您的MarshalByRefObject
继承类中起作用,您只需将目标dynamic object
设置为等于new ProxyDynamicObject(model)
。在我编写的示例中,我像这样打电话。
instance = Activator.CreateInstance(type);
var setModel = type.GetMethod(\"SetModel\",BindingFlags.Public | BindingFlags.Instance);
var render = type.GetMethod(\"Render\",BindingFlags.Public | BindingFlags.Instance);
setModel.Invoke(instance,new object[] { new ProxyDynamicObject(model) });
render.Invoke(instance,null);
我已经写了一篇有关它的博客文章http://buildstarted.com/2011/06/28/getting-anonymous-types-to-cross-the-appdomain-boundary/对其进行了更详细的说明。 (尽管这是我不太擅长的事情)
此实现肯定存在问题。它不支持嵌套的匿名类型,并且我确定它会在一般情况下中断。但这绝对是使您走上正确道路的方法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。