简体   繁体   中英

Repository returning objects implementing interfaces with generic types

I have a problem that I'm trying to wrap my head around. I might be terribly mistaken but here is what I'm trying to do.

I have two interfaces. The second interfaces has a property that should be of a implementation of the first interface. Something like this:

public interface ITypeA{
   int Id {get;set;}
}

public interface IEntityA<T>: where T:ITypeA
{
   string Name{get;set;}
   T type{get;set;}
}

The implementations looks like this:

public class TypeA: ITypeA{
  int Id {get;set;}
}

public class EntityA: IEntityA<TypeA>{
  public string Name{get;set;}
  public TypeA type{get;set;
}

I might be doing something wrong already(?).

Now I'm implementing the repository pattern, and the interface for that looks like this:

public interface IRepo{
   IEnumerable<IEntityA<ITypeA>> GetObjects();
}

and the implementation:

public class DefaultRepo:Repo{

  //Cunstructors

   public IEnumerable<IEntitytA<ITypeA>> GetObjects(){
      var objects = SomeMethodThatReturnsTheOjects();//Get objects as EntityA[];
      return object.ToList();
   }
}

This doesn't work.

I've tried to cast it as well, but getting a warning that it is a suspicious cast.

objects.Cast<IEntityA<ITypeA>[]>().ToList();

Where am I doing/thinking wrong?

Help much appriciated :)

EDIT: Maybe the repository interface declaration should look like this

public interface IRepo<TEntityA> where TEntityA:IEntityA{
       IEnumerable<TEntityA> GetObjects();
    }

and the implementation:

public class DefaultRepo:Repo<EntityA>{
   ///Methods
}

Thoughts?? :)

The repository should basically get json data and convert it into entities. However the json can look very diffrently from diffrent providers but it contains the same data (more or less). I set up the parsing with Json.NET and therefore have to specify the [JsonProperty] differently in the entity implementations that the repository returns

Why don't you just have:

public interface IUserRepository 
{
   IEnumerable<IUser> Find();
}

And then have UserFromSourceA , UserFromSourceB etc.

In that way you can use JSON.NET attributes with different implementations while still exposing the same user interface.

I've found a proper solution for this. I'm using json.net and I was able to solve it by doing this:

public interface ITypeA{
   int Id {get;set;}
}

public interface ITypeB{
   int id {get;set;}
}

public class TypeA:ITypeA
   string Name{get;set;}
   int id {get;set;}

   [JsonConverter(typeof (ConcreteTypeConverter<TypeB>))]
   ITypeB type{get;set;}
}

public class TypeB:ITypeB
{
   int id {get;set;}
}

And the converter looks like this:

 public class ConcreteTypeConverter<TConcrete> : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            //assume we can convert to anything for now
            return true;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            //explicitly specify the concrete type we want to create
            return serializer.Deserialize<TConcrete>(reader);
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            //use the default serialization - it works fine
            serializer.Serialize(writer, value);
        }
    }

The interfaces get cleaner and easier to read without the generics.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM