代码之家  ›  专栏  ›  技术社区  ›  bschreck

在不知道类型的情况下返回泛型对象?

  •  5
  • bschreck  · 技术社区  · 7 年前

    {
       "id":"1",
       "created_at":"2017-09-19T20:41:23.093Z",
       "type":"person.created",
       "object":{
          "id":"person1",
          "created_at":"2017-09-19T20:41:23.076Z",
          "updated_at":"2017-09-19T20:41:23.076Z",
          "firstname":"First",
          ...
       }
    }
    

    内部对象可以是任何对象,因此我认为这将是使用泛型的绝佳机会,并按如下方式构建了我的类:

    public class WebHookModel<T> where T : class, new()
    {
        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }
    
        [JsonProperty(PropertyName = "created_at")]
        public DateTime CreatedAt { get; set; }
    
        [JsonProperty(PropertyName = "type")]
        public string Type { get; set; }
    
        [JsonProperty(PropertyName = "object")]
        public T Object { get; set; }
    
        [JsonIgnore]
        public string WebHookAction
        {
            get
            {
                return string.IsNullOrEmpty(Type) ? string.Empty : Type.Split('.').Last();
            }
        }
    }
    

    然后创建以下界面:

    public interface IWebHookModelFactory<T> where T : class, new()
    {
       WebHookModel<T> GetWebHookModel(string type, string jsonPayload);
    }
    

    我没有理解的是,在编译时不知道类型是什么的情况下,我应该如何实现工厂类?

    稍微玩弄一下模型,我将其更改为带有抽象T对象的抽象类,以便它可以由派生类定义。

    public abstract class WebHookModel<T> where T : class, new()
    {
        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }
    
        [JsonProperty(PropertyName = "created_at")]
        public DateTime CreatedAt { get; set; }
    
        [JsonProperty(PropertyName = "type")]
        public string Type { get; set; }
    
        [JsonProperty(PropertyName = "object")]
        public abstract T Object { get; set; }
    
        [JsonIgnore]
        public string WebHookAction
        {
            get
            {
                return string.IsNullOrEmpty(Type) ? string.Empty : Type.Split('.').Last();
            }
        }
    }
    
    public PersonWebHookModel : WebHookModel<Person>
    {
        public override Person Object { get; set; }
    }
    

    案例陈述?

    public interface IWebHookFactory<TModel, TJsonObject> 
        where TJsonObject : class, new()
        where TModel : WebHookModel<TJsonObject>
    {
        TModel GetWebHookModel(string type, string jsonPayload);
    }
    

    public interface IWebHookService<TModel, TJsonObject>
        where TJsonObject : class, new()
        where TModel : WebHookModel<TJsonObject>
    {
        void CompleteAction(TModel webHookModel);
    }
    
    public abstract class BaseWebhookService<TModel, TJsonObject> : IWebHookService<TModel, TJsonObject>
            where TJsonObject : class, new()
            where TModel : WebHookModel<TJsonObject>
    {
        public void CompleteAction(TModel webHookModel)
        {
            var self = this.GetType();
            var bitWise = System.Reflection.BindingFlags.IgnoreCase
                            | System.Reflection.BindingFlags.Instance
                            | System.Reflection.BindingFlags.NonPublic;
    
            var methodToCall = self.GetMethod(jsonObject.WebHookAction, bitWise);
            methodToCall.Invoke(this, new[] { jsonObject });
        }
    
        protected abstract void Created(TModel webHookObject);
    
        protected abstract void Updated(TModel webHookObject);
    
        protected abstract void Destroyed(TModel webHookObject);
    }
    
    public class PersonWebHookService : BaseWebHookService<PersonWebHookModel, Person>
    {
        protected override void Created(PersonWebHookModel webHookModel)
        {
            throw new NotImplementedException();
        }
    
        protected override void Updated(PersonWebHookModel webHookModel)
        {
            throw new NotImplementedException();
        }
    
        protected override void Destroyed(PersonWebHookModel webHookModel)
        {
            throw new NotImplementedException();
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Mike S    7 年前

    解决方案的要点: 2.不知何故,您需要从JSON负载中的类型标记映射到实际的C#类。
    即,“person.created”,“-->“person”。
    如果控制序列化格式,则为JSON。Net可以插入自己的类型标记,并为您执行此操作。假设你不能走那条路。。。 因此,您需要像字典这样的东西来包含映射。

    abstract class WebhookPayload // Note this base class is not generic! 
    {
        // Common base properties here 
    
        public abstract void DoWork();
    }
    
    abstract class PersonPayload : WebhookPayload
    {
        public override void DoWork()
        {
            // your derived impl here 
        }
    }
    

        static Dictionary<string, Type> _map = new Dictionary<string, Type>
        {
            { "person.created", typeof(PersonPayload)}
        }; // Add more entries here 
    
        public static WebhookPayload Deserialize(string json)
        {
            // 1. only parse once!
            var jobj = JObject.Parse(json); 
    
            // 2. get the c# type 
            var strType = jobj["type"].ToString(); 
    
            Type type;
            if (!_map.TryGetValue(strType, out type))
            {
                // Error! Unrecognized type
            }
    
            // 3. Now deserialize 
            var obj = (WebhookPayload) jobj.ToObject(type);
            return obj;
        }