阅读其他帖子的普遍共识是序列化匿名代表和行动等是一个坏主意和脆弱等等。这些序列化行动的生命周期将很短暂,但我对如何完成什么的更好的想法持开放态度我在做。
我有一个Web角色和一个辅助角色。用户可以上传大量需要拆分并发送到外部wcf服务的数据。我需要排队这些数据,我只想要一个通用接口。我希望能够对其进行反序列化并在其上调用Execute(),而无需在worker角色中使用自定义逻辑。
我有4个外部服务(可能会增长),每个服务都有多个调用,并且有自己独特的参数。我想要一个在web角色中构造参数的方法,声明我要构造哪个serviceInvoker类和接口(生成具有客户端凭据的ChannelFactory等),并使用所述参数执行子方法。
// Code
var queueMessage = new WorkOutMessage<IService1>(User.agent.Client.Id,
new Action<ServiceInvoker<IService1>>(serviceInvoker =>
serviceInvoker.InvokeService(proxy =>
{
using (new OperationContextScope((IContextChannel)proxy))
{
OperationContext.Current.OutgoingMessageHeaders.ReplyTo = new EndpointAddress("https://someAddress.com/");
OperationContext.Current.OutgoingMessageHeaders.MessageId = new System.Xml.UniqueId(head.CorrelationID);
proxy.SomeChildFunction(envelope);
}
})));
var stream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(stream, queueMessage;
var brokeredMessage = new BrokeredMessage(stream) { CorrelationId = correlationId };
// Formatter.Serialize throws an exception
Type '<MyController>+<>c__DisplayClassc' in Assembly '<MyDll>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
// Classes
public interface IQueueProxyMessage
{
int Attempts();
bool Execute();
}
[Serializable]
public class WorkOutMessage<T> : IQueueProxyMessage where T : class
{
public Guid clientId { get; set; }
public Action<ServiceInvoker<T>> action { get; set; }
public int attempts { get; set; }
public WorkOutMessage(Guid clientId, Action<ServiceInvoker<T>> action)
{
this.clientId = clientId;
this.action = action;
this.attempts = 0;
}
public int Attempts()
{
return this.attempts;
}
public bool Execute()
{
this.attempts++;
try
{
var config = InfrastructureConfiguration.Instance;
var storage = new AzureStorageService();
var db = new DbContext(config.azure.dbConnectionString,
DbValidationMode.Enabled,
DbLazyLoadingMode.Disabled,
DbAutoDetectMode.Enabled);
var client = db.Client.Include(x => x.Organisation)
.Include(x => x.Certificate)
.Where(x => x.Active
&& x.Organisation.Active
&& x.Certificate != null
&& x.Id == this.clientId)
.FirstOrDefault();
if(client != null)
{
X509Certificate2 clientCert;
string clientCertContentType;
byte[] clientCertContent;
if (storage.GetBlob(AzureBlobType.Certificate, client.Certificate.StorageId.ToString(), out clientCertContentType, out clientCertContent))
{
var base64EncodedBytes = Encoding.Unicode.GetString(clientCertContent);
clientCert = new X509Certificate2(Convert.FromBase64String(base64EncodedBytes), "test", X509KeyStorageFlags.PersistKeySet);
if(clientCert != null)
{
var serviceInvoker = new ServiceInvoker<T>(client.Id, "test", clientCert, config.publicCertificate);
if(serviceInvoker != null)
{
this.action.Invoke(serviceInvoker);
}
// error
}
// error
}
// error
}
else
{
}
return true;
}
catch (Exception ex)
{
return false;
}
}
显然,我的序列化知识非常不存在。这就是为什么我认为这首先起作用的原因。有没有办法重新设计这个,所以我仍然可以指定使用什么serviceInvoker,什么方法和传递参数?
编辑:我尝试使用BinaryFormatter和Exception
的代码Edit2:这是一个坏主意,我将传递数据并在工作者上重建类。