Below is my generic class , I need to access GetAll method for that I need to create instance. How can I create instance if this class to access GetAll method.
Below is my code
public class GenericRepository<TContext> : IGenericRepository
where TContext : DbContext, new()
{
private TContext _entities;
public TContext Context
{
get { return _entities; }
set { _entities = value; }
}
public virtual List<TEntity> GetAll<TEntity>() where TEntity : class
{
try
{
_entities = new TContext();
return _entities.Set<TEntity>().ToList();
}
catch (Exception)
{
return null;
}
}
}
public interface IGenericRepository
{
List<TEntity> GetAll<TEntity>() where TEntity : class;
}
Because the class is a Generic class it needs to have a type passed to it when creating it like this.
IGenericRepository referenceToRepostoryObject = new GenericRepository<MyDbContextClassName>();
Is this what you need?
var d1 = typeof(GenericRepository<>);
Type[] typeArgs = { typeof(Item) };
var makeme = d1.MakeGenericType(typeArgs);
var repository = (IGenericRepository)Activator.CreateInstance(makeme);
repository.GetAll<Item>();
Related
Using this PipelineX class below, is there any way to resolve the filters applied to the pipline without injecting the autofac container and calling _container.Resolve();
public class PipelineX<T> : FilterBase<T>, IPipelineX<T>
{
private readonly IContainer _container;
public PipelineX(IContainer container)
{
_container = container;
}
protected override T Process(T input)
{
return input;
}
public PipelineX<T> FilterBy<X>()
{
var filter = _container.Resolve(typeof(X)) as IFilter<T>;
Register(filter);
return this;
}
}
To avoid the usage of Autofac as a service locator you can register your own factory method into it, in this case:
builder.Register<Func<Type, object>>((c, p) =>
{
var context = c.Resolve<IComponentContext>();
return type => context.Resolve(type);
});
and use that in your PipelineX class like this:
private readonly Func<Type, object> filterFactory;
public PipelineX(Func<Type, object> filterFactory)
{
this.filterFactory = filterFactory;
}
protected override T Process(T input)
{
return input;
}
public PipelineX<T> FilterBy<X>()
{
var filter = this.filterFactory(typeof(X)) as IFilter<T>;
Register(filter);
return this;
}
Consider: This only removes the hard reference to the Autofac container, it's still using an abstract object factory which is not self explanatory enough and should be replaced by a custom filter factory or selector implementation.
This is similar to Péter's answer but uses a custom factory:
public class FilterFactory
{
private readonly Func<Type, object> _factoryFunc;
public FilterFactory(Func<Type, object> factoryFunc)
{
_factoryFunc = factoryFunc ?? throw new ArgumentNullException(nameof(factoryFunc));
}
public IFilter<T> Create<X, T>()
{
IFilter<T> filter = Create<T>(typeof(X));
return filter;
}
public IFilter<T> Create<T>(Type type)
{
var filter = _factoryFunc(type) as IFilter<T>;
if (filter == null)
{
throw new ArgumentException($"Could not find filter for type '{type.FullName}'");
}
return filter;
}
}
PipelineX implementation would be:
public class PipelineX<T> : FilterBase<T>, IPipelineX<T>
{
private readonly FilterFactory _factory;
public PipelineX(FilterFactory factory)
{
_factory = factory;
}
protected override T Process(T input)
{
return input;
}
public PipelineX<T> FilterBy<X>()
{
var filter = _factory.Create<X,T>() as IFilter<T>;
Register(filter);
return this;
}
}
Registering the factory using Autofac:
builder.Register<FilterFactory>(c =>
{
var context = c.Resolve<IComponentContext>();
return new FilterFactory(context.Resolve);
});
I design some application with using Repository pattern. I have a generic repository:
public interface IGenericRepository<T> where T : class { // ... }
public class GenericRepository <T> : IGenericRepository<T> where T : class {// ... }
For example, I have two entities: Order and OrderLine.
For entity "Order" I need only generic repository methods, so it's OK.
But for entity "OrderLine" I need some generic repository methods and some addtitional. So, I create a custom repository, which extends generic:
public interface IOrderLinesRepository : IGenericRepository<OrderLine> {...}
public class OrderLinesRepository : GenericRepository<OrderLine>, IOrderLinesRepository
{
//... this is my additional methods here
}
But now I want to create method, which will return a repository by entity type.
If entity has a custom repository - it should be retuned. If not, method must return GenericRepository. Here is my attempt to create this.
public sealed class RepositoryFactory
{
// Here is custom repository types
private IDictionary<Type, Func<DbContext, object>> GetCustomFactories()
{
return new Dictionary<Type, Func<DbContext, object>>
{
{ typeof(OrderLine), dbContext =>
new OrderLinesRepository(dbContext) },
};
}
// Custom repository types
private IDictionary<Type, Type> GetRepositoryTypes()
{
return new Dictionary<Type, Type>
{
{ typeof(OrderLine), typeof(IOrderLinesRepository) }
};
}
private Func<GoodWillDbContext, object> GetDefaultFactory<T>()
where T : class
{
return dbContext => new GenericRepository<T>(dbContext);
}
private Func<DbContext, object> GetFactory<T>() where T : class
{
Func<DbContext, object> factory;
var factories = GetCustomFactories();
factories.TryGetValue(typeof(T), out factory);
return factory ?? (factory = GetDefaultFactory<T>());
}
public Type GetRepoType(Type type)
{
var types = GetRepositoryTypes();
Type repoType;
types.TryGetValue(type, out repoType);
return repoType;
}
public object MakeRepository<U>(DbContext dbContext) where U : class
{
// Get repository type
// If custom type not found, it should be standart type
// IGenericRepository<U>
var type = _repositoryFactory.GetRepoType(typeof(U)) ??
typeof(IGenericRepository<U>);
var f = _repositoryFactory.GetFactory<U>();
var repo = f(dbContext);
return repo;
}
}
But it's not working for some reason. I have some questions:
1. What type of return value should be in MakeRepository?
2. How should I cast var repo = f(dbContext); to repository type?
Or maybe there is another way to do what I need?
Your code seems really complicated for something that should be simple... The below example is just dummy code, feel free to adapt it to your needs.
public static class RepositoryFactory
{
public static IGenericRepository<T> MakeRepository<T>(DbContext context)
where T : class
{
var type = typeof(T);
if (type == typeof(Car))
{
return CarRepositoryFactory.CreateCarRpository(context);
}
else if (type == typeof(Boat))
{
return BoatRepositoryFactory.CreateBoatRepository(context);
}
}
}
How to use it:
var myRepo = (CarRepository)RepositoryFactory.MakeRepository(new MyContext());
These kind of codes are not meant to be modified frequently (you don't add a repository at each commit, do you? ;)), so do yourself a favor and keep it simple. :)
Edit : if you really want to keep your code, please add a comment to my response and I see want I'll can do. :)
So if I understand it correctly, you want to be able to get the repository type by the entity type. I modified your implementation a little and I got it to work as I believe it should.
public sealed class RepositoryFactory
{
public static RepositoryFactory Instance = new RepositoryFactory();
// Here is custom repository types
private IDictionary<Type, Func<DbContext, object>> GetCustomFactories()
{
return new Dictionary<Type, Func<DbContext, object>>
{
// { typeof(IOrderLinesRepository), dbContext => new OrderLinesRepository(dbContext) },
};
}
// Custom repository types
private IDictionary<Type, Type> GetRepositoryTypes()
{
return new Dictionary<Type, Type>
{
{ typeof(OrderLine), typeof(IOrderLinesRepository) }
};
}
private Func<DbContext, object> GetDefaultFactory<T>()
where T : class
{
return dbContext => new GenericRepository<T>(dbContext);
}
private Func<DbContext, object> GetFactory(Type factoryType)
{
if (factoryType == null) return null;
Func<DbContext, object> factory;
var factories = GetCustomFactories();
factories.TryGetValue(factoryType, out factory);
return factory;
}
public Type GetRepoType(Type type)
{
var types = GetRepositoryTypes();
Type repoType;
types.TryGetValue(type, out repoType);
return repoType;
}
public IGenericRepository<TEntity> MakeRepositoryByEntity<TEntity>(DbContext dbContext) where TEntity : class
{
var type = this.GetRepoType(typeof(TEntity));
var f = this.GetFactory(type) ?? GetDefaultFactory<TEntity>();
var repo = f(dbContext);
return (IGenericRepository<TEntity>)repo;
}
public TRepo MakeRepository<TRepo, TEntity>(DbContext dbContext)
where TRepo : class, IGenericRepository<TEntity>
where TEntity : class
{
var repo = this.MakeRepositoryByEntity<TEntity>(dbContext);
try
{
return (TRepo)repo;
}
catch (InvalidCastException)
{
throw new Exception($"Registered repository for entity ${typeof(TEntity).FullName} does not implement {typeof(TRepo).FullName}");
}
}
}
You can invoke it in one of two way:
var d = RepositoryFactory.Instance.MakeRepositoryByEntity<OrderLine>(dbContext);
var d2 = RepositoryFactory.Instance.MakeRepository<IOrderLinesRepository, OrderLine>(dbContext);
I am using a DataContractJsonSerializer to serialize an object graph. When I construct the objects, each receives a reference to an instance of a utility object (it's a factory, for creating instances of subclasses of an abstract contract class) - which works great until the graph is serialized and then deserialized again, whereupon the objects no longer have a reference to the utility object any more. I need this reference. How would you recommend I implement this (singletons don't work because separate graphs need their own instance of the object)?
Another way to accomplish is to introduce a thread static or thread local factory object, then populate your classes with it using an [OnDeserializing] callback.
Thus, if you define your types as follows:
public interface IFactory
{
}
public class Factory : IFactory
{
}
public interface IHasFactory
{
IFactory Factory { get; }
}
[DataContract]
public abstract class HasFactoryBase : IHasFactory
{
[ThreadStatic]
static IFactory deserializedFactory;
static IFactory DeserializedFactory
{
get
{
return deserializedFactory;
}
set
{
deserializedFactory = value;
}
}
public static IDisposable SetDeserializedFactory(IFactory factory)
{
return new PushValue<IFactory>(factory, () => DeserializedFactory, val => DeserializedFactory = val);
}
IFactory factory;
public IFactory Factory { get { return factory; } }
public HasFactoryBase(IFactory factory)
{
this.factory = factory;
}
[OnDeserializing]
void OnDeserializing(StreamingContext context)
{
this.factory = DeserializedFactory;
}
}
public struct PushValue<T> : IDisposable
{
Action<T> setValue;
T oldValue;
public PushValue(T value, Func<T> getValue, Action<T> setValue)
{
if (getValue == null || setValue == null)
throw new ArgumentNullException();
this.setValue = setValue;
this.oldValue = getValue();
setValue(value);
}
#region IDisposable Members
// By using a disposable struct we avoid the overhead of allocating and freeing an instance of a finalizable class.
public void Dispose()
{
if (setValue != null)
setValue(oldValue);
}
#endregion
}
[DataContract]
public class Foo : HasFactoryBase
{
public Foo(IFactory factory)
: base(factory)
{
this.Bars = new List<Bar>();
}
[DataMember]
public List<Bar> Bars { get; set; }
}
[DataContract]
public class Bar : HasFactoryBase
{
public Bar(IFactory factory) : base(factory) { }
}
You can serialize and deserialize as follows:
var factory = new Factory();
var test = new Foo(factory)
{
Bars = { new Bar(factory) },
};
var serializer = new DataContractJsonSerializer(test.GetType());
byte [] json;
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, test);
json = stream.ToArray();
}
Foo test2;
using (HasFactoryBase.SetDeserializedFactory(factory))
using (var stream = new MemoryStream(json))
{
test2 = (Foo)serializer.ReadObject(stream);
}
if (test2.Factory != test.Factory)
throw new InvalidOperationException();
And the JSON will look like:
{
"Bars": [
{}
]
}
Some notes:
The factory object does not appear at all in the JSON.
The factory objects no longer need to inherit from some abstract base class, they can simply implement a common IFactory interface.
One way to accomplish this is with a data contract surrogate. Using surrogates, you can replace your "real" factory with a dummy stub during serialization. Then, during deserialization, replace the dummy with the desired factory.
Thus, if your classes look something like:
public abstract class FactoryBase
{
}
public class Factory : FactoryBase
{
}
public interface IHasFactory
{
FactoryBase Factory { get; }
}
[DataContract]
public abstract class HasFactoryBase : IHasFactory
{
[DataMember(IsRequired = true)]
FactoryBase factory;
public FactoryBase Factory { get { return factory; } }
public HasFactoryBase(FactoryBase factory)
{
this.factory = factory;
}
}
[DataContract]
public class Foo : HasFactoryBase
{
public Foo(FactoryBase factory)
: base(factory)
{
this.Bars = new List<Bar>();
}
[DataMember]
public List<Bar> Bars { get; set; }
}
[DataContract]
public class Bar : HasFactoryBase
{
public Bar(FactoryBase factory) : base(factory) { }
}
You define an IDataContractSurrogate to replace all occurrences of FactoryBase with a surrogate as follows:
public class FactorySurrogateSelector : IDataContractSurrogate
{
[DataContract]
class FactorySurrogate
{
}
readonly FactoryBase factory;
public FactorySurrogateSelector(FactoryBase factory)
{
this.factory = factory;
}
#region IDataContractSurrogate Members
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
throw new NotImplementedException();
}
public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
{
throw new NotImplementedException();
}
public Type GetDataContractType(Type type)
{
if (typeof(FactoryBase).IsAssignableFrom(type))
return typeof(FactorySurrogate);
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
if (obj is FactorySurrogate)
return factory;
return obj;
}
public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
{
throw new NotImplementedException();
}
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj is FactoryBase)
{
return new FactorySurrogate();
}
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
throw new NotImplementedException();
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
throw new NotImplementedException();
}
#endregion
}
Then, serialize and deserialize as follows:
var factory = new Factory();
var test = new Foo(factory)
{
Bars = { new Bar(factory) },
};
var surrogate = new FactorySurrogateSelector(factory);
var serializer = new DataContractJsonSerializer(test.GetType(), Enumerable.Empty<Type>(), int.MaxValue, false, surrogate, false);
byte[] json;
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, test);
json = stream.ToArray();
}
Foo test2;
using (var stream = new MemoryStream(json))
{
test2 = (Foo)serializer.ReadObject(stream);
}
if (test2.Factory != test.Factory)
throw new InvalidOperationException();
Notice that the desired factory was passed directly into the constructor of the FactorySurrogateSelector, then eventually set inside each type that contains instances of the factory type.
The resulting JSON will look like:
{
"factory": {},
"Bars": [
{
"factory": {}
}
]
}
Some qualifications:
Your factory must inherit from some common base class, here FactoryBase. The data contract serializers will never serialize an interface member, e.g. IFactory factory where IFactory is your factory interface, even when there is an applicable surrogate.
The empty "factory": {} objects must appear in the JSON in order for the surrogate to inject the correct "real" factory value during deserialization. Hence the [DataMember(IsRequired = true)].
This question already has answers here:
How do I use reflection to call a generic method?
(8 answers)
Closed 8 years ago.
Given the following Interfaces:
interface IEntity
{
int Id{get;}
}
interface IPerson : IEntity
{
string Name{get;}
int Age{get;}
}
interface ITeacher : IPerson
{
string StaffId{get;}
}
interface IStudent : IPerson
{
string StudentId{get;}
string Courses{get;}
}
interface IRepository
{
T Get<T>(int id) where T : IEntity
}
I have the following classes in my namespace
public class EntityBase() : IEntity
{
int Id{get;set;}
}
public class Teacher : EntityBase, ITeacher{}
public class Sudent : EntityBase, IStudent{}
Currently I am implementing this IRepository as follows:
class Repository: IRepository
{
IDataContext Context{get;set;}
T Get<T>(int id) where T : EntityBase
{
if(typeof(T) == typeof(Teacher))
return Context.Get<ITeacher>(id);
if(typeof(T) == typeof(Sudent))
return Context.Get<ISudent>(id);
throw new Exception("Unknown Interface " + typeof(T).Name);
}
}
Is there a betterway of implementing this? Given that our Context has no knowledge of our data types (Teacher, Student), just its interfaces (ITeacher, IStudent).
Can something like this work?
class Repository: IRepository
{
T Get<T>(int id) where T : EntityBase
{
var MyInterface = FindInterface<T>();
return Context.Get<MyInterface>(id);
}
}
I think this will do:
class Repository: IRepository
{
IDataContext Context{get;set;}
T Get<T>(int id) where T : EntityBase
{
string[] interfaceList = new string[]
{ "ITeacher", "IStudent"};
Type interfaceType = null;
foreach (string s in interfaceList)
{
var types = typeof(T).FindInterfaces((x, y) => x.Name == y.ToString(), s);
if (types.Length > 0)
interfaceType = types[0];
}
if (interfaceType == null)
throw new Exception("Unknown Interface " + typeof(T).Name);
MethodInfo method = typeof(Context).GetMethod("Get");
MethodInfo generic = method.MakeGenericMethod(interfaceType);
var returnValue = generic.Invoke(Context, new object[] { id });
return (T)Convert.ChangeType(returnValue, typeof(T));
}
}
EDIT: As I don't know the name of your namespace, I have used the Name property to filter the interfaces. In real world usage I will suggest that you use FullName just to be sure, like this:
...
string[] interfaceList = new string[]
{ "MyNamespace.ITeacher", "MyNamespace.IStudent"};
...
var types = typeof(T).FindInterfaces((x, y) => x.FullName == y.ToString(), s);
I think you can accomplish this through reflection by finding the Get method on Context class, and invoking it as a generic call for the caller-supplied type T. I haven't tested this, but the code should look something like this:
T Get<T>(int id) where T : EntityBase
{
Type context = Context.GetType();
MethodInfo getMethod = context.GetMethod("Get", BindingFlags.Public);
MethodInfo genericGet = getMethod.MakeGenericMethod(new [] {typeof(T)});
return (T)genericGet.Invoke(Context, new object[] { id } );
}
It looks to me like you mean it the other way around. You don't want to pass interface types to Context.Get<>, do you?
// is this what you mean?
if (typeof(T) == typeof(ITeacher))
return Context.Get<Teacher>(id);
If it is, you'll need to use MakeGenericMethod, see this for an example (note the caching part).
If it is not, you might be misunderstanding some concepts of LINQ and/or Repository pattern.
However I'm curious why did you decide to use interfaces. LINQ objects are POCO anyways, why adding another layer of abstraction which involves (grrsh!) calling generic methods on DataContext via reflection?
A simple return Context.Get<T>(id) could be accomplished as following:
class Repository : IRepository
{
public IDataContext Context { get; set; }
public T Get<T>(int id) where T : IEntity, new()
{
return Context.Get<T>(id);
}
}
Following is your object/interface model with implementation for the Context
interface IEntity
{
int Id{get;}
}
interface IPerson : IEntity
{
}
interface ITeacher : IPerson
{
}
interface IStudent : IPerson
{
}
interface IDataContext
{
T Get<T>(int id) where T:new();
}
interface IRepository
{
T Get<T>(int id) where T : IEntity , new() ;
}
public class EntityBase : IEntity
{
public virtual int Id{get;set;}
}
public class Teacher : EntityBase, ITeacher {
int id=0;
public override int Id {
get { return this.id; }
set { this.id = value; }
}
}
public class Student : EntityBase, IStudent
{
int id=0;
public override int Id {
get { return this.id; }
set { this.id = value; }
}
}
class Context<T>: IDataContext where T: EntityBase, new()
{
ArrayList store;
public Context(int dataSize)
{
store = new ArrayList(dataSize);
for (int i = 0; i < dataSize; i++)
{
T t = new T();
t.Id = i;
store.Add(t);
}
}
public T Get<T>(int i) where T:new()
{
if (i<store.Count)
{
return (T)store[i];
}
else
{
return default(T);
}
}
}
Now finally the main method class to demonstrate that it all hangs together nicely.
using System;
using System.Collections;
class MyClass
{
static void Main(string[] args)
{
Context<Teacher> teachersContext = new Context<Teacher>(100);//contructs a db of 100 teachers
Context<Student> studentsContext = new Context<Student>(100);//contructs a db of 100 teachers
Repository repo = new Repository();
// set the repository context and get a teacher
repo.Context = teachersContext;
Teacher teacher1 = repo.Get<Teacher>(83); //get teacher number 83
Console.WriteLine("Teacher Id:{0} ", teacher1.Id);
// redirect the repositry context and now get a student
repo.Context = studentsContext;
Student student1 = repo.Get<Student>(35); //get student number 35
Console.WriteLine("Student Id: {0} ", student1.Id);
Console.ReadLine();
}
Is there any way to move the Parse method into the abstract class ? I tried multiple ways (links at the bottom), but I am still hitting one or another roadblock.
public class AnimalEntityId : EntityId<AnimalEntityId>
{
public AnimalEntityId()
: base()
{
}
private AnimalEntityId(string value)
: base(value)
{
}
public static AnimalEntityId Parse(string value)
{
return new AnimalEntityId(value);
}
}
public abstract class EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
}
Tried these suggestions with no luck:
Passing arguments to C# generic new() of templated type
Is there a generic constructor with parameter constraint in C#?
https://social.msdn.microsoft.com/Forums/en-US/fd43d184-0503-4d4a-850c-999ca58e1444/creating-generic-t-with-new-constraint-that-has-parameters?forum=csharplanguage
http://www.gamedev.net/topic/577668-c-new-constraint--is-it-possible-to-add-parameters/
Thanks in advance!
If you don't mind using reflection, you can move Parse into the abstract type like this:
public static TEntityId Parse(string val) {
var constr = typeof(TEntityId).GetConstructor(
// Since the constructor is private, you need binding flags
BindingFlags.Instance | BindingFlags.NonPublic
, null
, new[]{ typeof(string) }
, null);
if (constr == null) {
throw new InvalidOperationException("No constructor");
}
return (TEntityId)constr.Invoke(new object[] {val});
}
Demo.
No, you cannot write a template constraint such as new(string) instead of simply new(). You'll have to leverage reflection to get it to work:
public abstract class EntityId<TEntityId>
where TEntityId : EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
public static TEntityId Parse(string value)
{
return (TEntityId)Activator.CreateInstance(typeof(TEntityId), new object[] { value });
}
}
Assuming you make the constructor accessible (instead of it currently being private). Note the constraint where TEntityId : EntityId<TEntityId> - which will ensure we'll only return subclasses of EntityId
How about making value a private mutable field/property and actually setting it from the Parse method?
(Curiously recurring generic parameter removed from EntityId for simplicity)
public class SimpleAnimalEntityId : EntityId
{
// Implicit parameterless constructor.
}
public class ParametrizedAnimalEntityId : EntityId
{
// Parametrized constructor only.
public ParametrizedAnimalEntityId(int ignored)
{
}
}
public abstract class EntityId
{
// Simple scenario: derived type has a parameterless constructor.
public static TEntity Parse<TEntity>(string value)
where TEntity : EntityId, new()
{
Guid id = Guid.Parse(value);
return new TEntity { value = id };
}
// Advanced scenario: derived type constructor needs parameters injected.
public static TEntity Parse<TEntity>(string value, Func<TEntity> constructor)
where TEntity : EntityId
{
Guid id = Guid.Parse(value);
TEntity entity = constructor();
entity.value = id;
return entity;
}
private Guid value;
protected EntityId()
{
value = Guid.NewGuid();
}
}
Now you can handle any constructor from your Parse method:
string id = Guid.NewGuid().ToString();
SimpleAnimalEntityId simple = EntityId.Parse<SimpleAnimalEntityId>(id);
ParametrizedAnimalEntityId parametrized = EntityId.Parse(id, () => new ParametrizedAnimalEntityId(42));