C# 嵌套操作的序列化<;T>;服务总线队列

C# 嵌套操作的序列化<;T>;服务总线队列,c#,.net,serialization,C#,.net,Serialization,阅读其他帖子的普遍共识是,序列化匿名代理和操作等是一个坏主意,而且很脆弱。这些序列化操作的生命周期将非常短暂,但我愿意接受关于如何完成我正在做的事情的更好想法 我有一个web角色和一个worker角色。用户可以上传我需要拆分并发送到外部wcf服务的大量数据。我需要对这些数据进行排队,我只需要一个通用接口。我希望能够对其进行反序列化并对其调用Execute(),而无需在worker角色中使用自定义逻辑 我有4个外部服务(可能会增长),每个都有多个呼叫,并且有自己独特的参数。我需要一种方法来构造we

阅读其他帖子的普遍共识是,序列化匿名代理和操作等是一个坏主意,而且很脆弱。这些序列化操作的生命周期将非常短暂,但我愿意接受关于如何完成我正在做的事情的更好想法

我有一个web角色和一个worker角色。用户可以上传我需要拆分并发送到外部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;
        }
    }
//代码
var queueMessage=new WorkOutMessage(User.agent.Client.Id,
新操作(serviceInvoker=>
serviceInvoker.InvokeService(代理=>
{
使用(新OperationContextScope((IContextChannel)代理))
{
OperationContext.Current.OutgoingMessageHeaders.ReplyTo=新端点地址(“https://someAddress.com/");
OperationContext.Current.OutgoingMessageHeaders.MessageId=new System.Xml.UniqueId(head.CorrelationID);
SomeChildFunction(信封);
}
})));
var stream=newmemoryStream();
var formatter=新的二进制格式化程序();
序列化(流,队列消息;
var brokeredMessage=newbrokeredmessage(流){CorrelationId=CorrelationId};
//Serialize引发异常
程序集中的类型“+c__DisplayClassc”,版本=1.0.0,区域性=neutral,PublicKeyToken=null”未标记为可序列化。
//班级
公共接口IQueueProxyMessage
{
int尝试();
bool Execute();
}
[可序列化]
公共类WorkOutMessage:iqueueproxy消息,其中T:class
{
公共Guid客户端ID{get;set;}
公共操作动作{get;set;}
公共int尝试{get;set;}
公共工作消息(Guid客户端ID,操作)
{
this.clientId=clientId;
这个动作=动作;
该值为0;
}
公共int尝试次数()
{
把这个还给我;
}
公共bool Execute()
{
这个;
尝试
{
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.org)
.包括(x=>x.Certificate)
.其中(x=>x.活动
&&积极的
&&x.证书!=null
&&x.Id==this.clientId)
.FirstOrDefault();
如果(客户端!=null)
{
X509Certificate2客户证书;
字符串clientCertContentType;
字节[]clientCertContent;
if(storage.GetBlob(AzureBlobType.Certificate,client.Certificate.StorageId.ToString(),out clientCertContentType,out clientCertContent))
{
var base64EncodedBytes=Encoding.Unicode.GetString(clientCertContent);
clientCert=new X509Certificate2(转换.FromBase64String(base64EncodedBytes),“测试”,X509KeyStrageFlags.PersistKeySet);
if(clientCert!=null)
{
var serviceinvocker=newserviceinvocker(client.Id,“test”,clientCert,config.publicCertificate);
if(serviceInvoker!=null)
{
this.action.Invoke(serviceInvoker);
}
//错误
}
//错误
}
//错误
}
其他的
{
}
返回true;
}
捕获(例外情况除外)
{
返回false;
}
}
显然,我的序列化知识是不存在的。这就是为什么我认为这会在第一时间起作用。有没有办法重新构建它,以便我仍然可以指定要使用的serviceInvoker、方法和传递参数

编辑:我尝试使用BinaryFormatter和Exception的代码


Edit2:这是一个坏主意,我将传递数据并在worker上重建类。

这是否有效?引发了什么类型的异常?添加了异常,我假设这是由于它实例化了操作?或者我可能会从堆栈中传递一个变量?异常很明显:被序列化的类没有
Serializable
属性,从外观上看,由于它是匿名类型,它永远不会得到一个。您可能会尝试改用DataContractSerializer,但我不希望您尝试序列化的类能够很好地发挥作用。看起来您正在尝试序列化活动对象。请尝试序列化参数,然后重新创建活动对象看看:是的,经过一些讨论,我认为这是一个糟糕的想法。我将传递数据并在工人身上重建类。