Invoke method from base class using reflection - c#

I implemented generic repository pattern and unitofwork. I used basic patterns and they work great. In project I have requirement which says, every table has several fields which contains long, really long text, and user should have ability chose and open any of it. As each field named differently i decided to use power ov generics with reflection, to write method which resieves table name and field name and returns it.
Method, in generic Repository class, i wrote looks like this, it seems work properly
public interface IRepository<T> where T : class
{
//other methods
string GetPropertyByName(int id, string property);
}
public class Repository<T> : IRepository<T> where T : class
{
// other methods. add, edit, delete...
public string GetPropertyByName(int id, string property)
{
T model = this.Get(id);
var obj = model.GetType().GetProperty(property).GetValue(model, null);
return obj != null ? obj.ToString() : null;
}
}
I creted model classes for tables with help EF. Some tables binds directly genric repository, while other have separate interface and its implementation, as they require additional method. Example:
public interface ICompanyRepo : IRepository<COMPANY>
{
//some methods
}
public class CompanyRepo : Repository<COMPANY>, ICompanyRepo
{
//implementations of interface methods
}
And UOW implementation:
public interface IUnitOfWork
{
ICompanyRepo Company { get; }
IRepository<CURRENCY> Currency { get; }
}
public class UnitOfWork : IUnitOfWork
{
static DBEntities _context;
private UZMEDEXPORTEntities context
{
get
{
if (_context == null)
_context = new DBEntities();
return _context;
}
}
public UnitOfWork()
{
_context = context;
Company = new SP_CompanyRepo();
Currency = new Repository<CURRENCY>();
}
public ICompanyRepo Company { get; private set; }
public IRepository<CURRENCY> Currency { get; private set; }
}
I have problem on invoking GetPropertyByName() method in business layer.
I tried this:
public string GetHistory(string tableName, string fieldName, int id)
{
var prop = unitOfWork.GetType().GetProperty(tableName);
MethodInfo method;
method = prop.PropertyType.GetMethod("GetPropertyByName"); //try to find method
if(method == null) //if method not found search for interface which contains that method
method = prop.PropertyType.GetInterface("IRepository`1").GetMethod("GetPropertyByName");
var res = method.Invoke(prop, new object[] { id, fieldName });
return (string)res;
}
Which returns System.Reflection.TargetException. As I understood the problem is whith unitofwork implementation. In my invoke method "prop" is type of interface (ICompanyRepo), but invoke's target should be interface implementation class, in this case "CompanyRepo".
I could not find how to identify type of implementetion class, and solve this problem. Any help is appropriated

I am not sure that this is best option, but problem solved with use of ToExpando() extension given here. With this extension i could loop throw all properties of unitofwork and find required property by its name.
var propValue = unitOfWork.ToExpando().Single(x => x.Key == prop.Name).Value;
var res = method.Invoke(propValue, new object[] { id, fieldName });
Now method is invoking properly. May be there is cleaner solution, and I still hope to find this. For now i am going to use this solution, and just realised that I must read and practice a lot about reflections, dynamics and generics.
P.S Special thanks to Alexei for important notes and advices

Related

Binding wrapper classes with ninject

I have an interface that represents a table in a 3rd party API. Each instance provides the ability to search a single table using forward-only cursors:
public interface ITable
{
string TableName { get; }
ICursor Search(string whereClause);
}
I have written a wrapper class to handle searching an ITable and returning an enumerable instead (it's a little more complex than that in reality, but sufficient for showing my issue):
public interface ITableWrapper
{
IEnumerable<object> Search(string whereClause);
}
public class TableWrapper : ITableWrapper
{
private ITable _table;
public TableWrapper(ITable table)
{
_table = table;
}
public IEnumerable<Row> Search(string whereClause)
{
var cursor = _table.Search(whereClause);
while(cursor.Next())
{
yield return cursor.Row;
}
}
}
I then have several repository classes that should have a table wrapper injected:
public class Table1Repository
{
private ITableWrapper _table;
public Table1Reposiroty(ITableWrapper table)
{
_table = table;
}
//repository methods to actually do things
}
Since each table will have its own wrapper, and repositories need the correct table injecting, my thought was to use named bindings on the tables and wrappers so that ninject provides the correct instance. Thus the above class would have NamedAttribute applied to the constructor argument, and the binding would be as follows:
public void NinjectConfig(IKernel kernel, ITableProvider provider)
{
Bind<ITable>().ToMethod(ctx => provider.OpenTable("Table1")).Named("Table1").InSingletonScope();
Bind<ITableWrapper>().ToMethod(ctx => new TableWrapper(ctx.ContextPreservingGet<ITable>("Table1"))).Named("Table1Wrapper").InSingletonScope();
}
My questions are:
Is there a cleaner way to express this binding? I was thinking maybe a way to bind ITableWrapper once and have a new instance returned for each named ITable, with the repository constructor parameter attribute picking the named ITable for which it wants the ITableWrapper.
If the ITable should never be used by anything, and everything should always use ITableWrapper, is it ok (or even recommended) to bind just ITableWrapper and have that combine both ToMethod contents:
public void NinjectConfig(IKernel kernel, ITableProvider provider)
{
Bind<ITableWrapper>().ToMethod(ctx => new TableWrapper(provider.OpenTable("Table1"))).Named("Table1Wrapper").InSingletonScope();
}
There's no Ninject-built-in way to provide metadata to Ninject by attribute. The only thing it supports is the ConstraintAttribute (and the NamedAttribute as a subclass). This can be used to select a specific binding, but it can't be used to provide parameters for a binding.
So, in case you don't want to add a lot of code, the easiest and most concise way is along of what you suggested yourself:
public static BindTable(IKernel kernel, ITableProvider tableProvider, string tableName)
{
kernel.Bind<ITableWrapper>()
.ToMethod(ctx => new tableWrapper(tableProvider.OpenTable(tableName))
.Named(tableName);
}
(I've used the same string-id here for both table name and ITableWrapper name - this way you don't need to map them).
Also, i think it's better not to create a binding for ITable if you're not going to use it, anyway.
note: If you were to create the ITableWrapper by a factory (instead of ctor-injecting it), you could use parameters and a binding which reads the table-id from the parameter. Meaning a single binding would suffice.
Generic Solution
Now in case you're ok with adding some custom code you can actually achieve a generic solution. How? you add a custom attribute to replace the NamedAttribute which provides the table name. Plus you create a binding which reads the table name from this custom attribute. Let's say:
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class TableIdAttribute : Attribute
{
public TableIdAttribute(string tableName)
{
TableName = tableName;
}
public string TableName { get; private set; }
}
let's implement an IProvider to capsule the added binding complexity (it would also work with a ToMethod binding):
internal class TableWrapperProvider : Provider<ITableWrapper>
{
private readonly ITableProvider _tableProvider;
public TableWrapperProvider(ITableProvider tableProvider)
{
_tableProvider = tableProvider;
}
protected override ITableWrapper CreateInstance(IContext context)
{
var parameterTarget = context.Request.Target as ParameterTarget;
if (parameterTarget == null)
{
throw new ArgumentException(
string.Format(
CultureInfo.InvariantCulture,
"context.Request.Target {0} is not a {1}",
context.Request.Target.GetType().Name,
typeof(ParameterTarget).Name));
}
var tableIdAttribute = parameterTarget.Site.GetCustomAttribute<TableIdAttribute>();
if (tableIdAttribute == null)
{
throw new InvalidOperationException(
string.Format(
CultureInfo.InvariantCulture,
"ParameterTarget {0}.{1} is missing [{2}]",
context.Request.Target,
context.Request.Target.Member,
typeof(TableIdAttribute).Name));
}
return new TableWrapper(_tableProvider.Open(tableIdAttribute.TableName));
}
}
and here's how we use it (example classes):
public class FooTableUser
{
public FooTableUser([TableId(Tables.FooTable)] ITableWrapper tableWrapper)
{
TableWrapper = tableWrapper;
}
public ITableWrapper TableWrapper { get; private set; }
}
public class BarTableUser
{
public BarTableUser([TableId(Tables.BarTable)] ITableWrapper tableWrapper)
{
TableWrapper = tableWrapper;
}
public ITableWrapper TableWrapper { get; private set; }
}
and here's the bindings plus a test:
var kernel = new StandardKernel();
kernel.Bind<ITableProvider>().ToConstant(new TableProvider());
kernel.Bind<ITableWrapper>().ToProvider<TableWrapperProvider>();
kernel.Get<FooTableUser>().TableWrapper.Table.Name.Should().Be(Tables.FooTable);
kernel.Get<BarTableUser>().TableWrapper.Table.Name.Should().Be(Tables.BarTable);

How can I call a generic method on an injected class without informing the parent class of the generic type?

Below is the implementation of a dependency that is injected into another class.
public class CsvDataProvider : ICsvDataProvider
{
readonly ICsvReaderFactory _factory;
public CsvDataProvider(ICsvReaderFactory factory)
{
_factory = factory;
}
public IEnumerable<TRecord> GetData<TRecord>(string filepath) where TRecord : class
{
var reader = _factory.CreateCsvReader(filepath);
return reader.GetRecords<TRecord>();
}
}
The reader that is created by the factory will read all lines in a CSV file and convert each line to an instance of TRecord. I do not own the reader code and can not change the GetRecords<TRecord>() method.
This is where I am stuck:
public class CsvDataMigrationController
{
readonly ICsvDataProvider _provider;
readonly ICsvDataMigration _migration;
public CsvDataMigrationController(ICsvDataProvider provider, ICsvDataMigration migration)
{
_provider = provider;
_migration = migration;
}
public void ProcessFile(string path)
{
var records = _provider.GetData<I_DONT_WANT_TO_EXPLICITLY_SAY>(path); //<-- Help!
_migration.Migrate(records);
}
}
The intent is to inject a data provider and a migration procedure class into CsvDataMigrationController. The controller would call the data provider to get the data and pass the data into the migration class.
I don't want the CsvDataMigrationController to know about the type of data involved.
I don't want the CsvDataProvider to know about the migration.
I don't want the CsvDataMigration to know about where the data came from.
Any advice on how I can achieve this?
Note: I did not include the CsvDataMigration class because I didn't think it was useful in the explanation, but will include it if needed.
Well, since you can't change GetRecords, then perhaps the most straightforward way is to ask the migration interface for the record type, and use reflection to call the generic GetData method with that runtime-obtained type. Something like:
public void ProcessFile(string path)
{
Type recordType = _migration.InputRecordType;
var getDataMethod =
_provider.GetType()
.GetMethod("GetData")
.MakeGenericMethod(recordType);
var records = getDataMethod.Invoke(_provider, new object[] { path });
_migration.Migrate(records);
}
Typically, you will define a non-generic alternative such as
public interface ICsvDataProvider
{
IEnumerable GetData(string filepath, Type recordType)
IEnumerable<TRecord> GetData<TRecord>(string filepath)
where TRecord : class;
}
So you could call this as
public class CsvDataMigrationController
{
private string targetTypeName = ...;
public void ProcessFile(string path)
{
var recordType = Type.GetType(this.targetTypeName);
var records = _provider.GetData(path, recordType);
_migration.Migrate(records);
}
}
In this way, the generic method is just a bit of syntactic sugar around the non-generic method.
Using reflection (as in #Cameron's answer) is another solution. In both cases you must know the target type at run time (rather than at compile time as the generic method requires).

Lazy loading or proxy pattern in my library

Hi i'm writing a simple ORM DLL. The library works fine and i would like add some addone - Lazy Loading.
But i don't know how to implements that. I have one proposition.
In my orm (i have creator but never mind) User should create DB class who implements IMapper and set mapper class.
Somethink linke this.
public class Person
{
public virtual string Name {get;set;}
public virtual int Age {get; set;}
}
public class DataBase : IMapper
{
MapperSet<Person> Persons = new MapperSet<Person>();
}
If we have that class, and setup connectionString, we can take the data from DB. It's very similar to Entity Framework
Person p = Persons.Single(x=>x.Name == "John");
In that moment, i will check the all properties in mapping class and if are virtual then not return a that class, but Lazy Loading class.
I think out one conception. Not return (in that example) Person class but the class who extends Person class, and override all properties.
public class PersonReturn : Person
{
//here i must create a method who really take the data from db
private string Query = "SELECT TOP(1) FROM Person WHERE Name = 'John'";
private Execute()
{
p = (Person)Db.TableToObject(Query);
}
Person p;
public override string Name
{
get
{
if(p == null)
p = Execute();
return p.Name;
}
set {}
}
//same
public override int Age {get; set;}
}
User shouldn't see any change with using that class (only in debug it maybe see other class) it's should work as magic :P
My questions are :
1. How is implement Lazy Loading in for example Entity Framework, anybody know ?
2. Is simpler way from my proposition ? In my idea i must use TypeBuilder and Emit with IL source code - i hear it's problems with properties
they aren't be use in normaly way.
Use Castle.DynamicProxy (same proxy that nhibernate uses)
Lazy loading is implemented by generating inheritor at runtime and override all methods.
public class A
{
virtual protected string name { get; set; }
}
public interface IInterceptor
{
object Invoke(MethodInfo method, params object[] arguments);
}
public sealed class AProxy : A
{
static private readonly MethodInfo getname = typeof(A).GetProperty("name", ...).GetGetMethod(true);
static private readonly MethodInfo setname = typeof(A).GetProperty("name", ...).GetSetMethod(true);
private readonly IInterceptor interceptor;
public AProxy(IInterceptor interceptor)
{
this.interceptor = interceptor;
}
override protected string name
{
get { return this.interceptor.Invoke(AProxy.getname); }
set { this.interceptor.Invoke(AProxy.setname, value); }
}
}
Proxy factory have to to
return new AProxy(custominterceptor);
custominterceptor must take id of your entity and in first usage instantiate A, query database to populate A and delegate call to A.
AProxy must be generated (postbuild or at runtime using TypeBuilder)

Availability of Methods on the basis of Constructor

I have a Class called Repository for accessing (Read/Write to and from) Database.
The projects that require access to the database create an object of Repository and pass the connection string as a constructor parameter for the repository to work for that particular project.
I have few methods in the Repository that i want to be available only if certain connection strings are passed. I don't want them to be available if some different connection string is passed.
Is there any way I can accomplish that?
I have never used method header technique, can that help? if yes, how can i use it? if no, please let me know if there is any other way to achieve my goal.
Regards.
You could use a factory method pattern to accomplish your goal.
Create a RepositoryFactory class that takes in the connection string and returns a different repository based upon the contents of the string.
public class RepositoryFactory {
public IRepository GetRepository(string connection)
{
if(SomeTestOnConnect(connection))
return new SimpleRepository(connection);
else
return new FullRepository(connection);
}
}
With this when someone wants a repository they call the GetRepository method.
Sort of doing:
if (_connection == "XYZ")
throw new InvalidOperationException();
Is it possible that you could refactor your approach to create a new class:
public class ConnectionInfo
{
public string ConnectionString { get; set; }
public bool IsLimitedAccess { get; set; }
}
Then, in each repository method not allowed, if limited access, return null or throw exception or something?
If you know in advance whether you'll need the extra methods, you could have a base version which doesn't support the extra methods, and a derived type which does. The constructor for the derived type could throw an exception if required information is not provided.
Using a factory method instead of a constructor would allow a base or fancy object to be constructed based upon the passed-in connection string; if you just have one factory method, though, you'll have to typecast the result if you want to use the extra methods.
The best approach may be to have a factory method for each defined type, with a guarantee that it will either return an object that's at least as good as the requested type or throw an exception if it can't. This approach would allow for future expansion in case more further-derived types become available.
If you want to limit the available methods, you could use a pattern like this.
Use the factory to get an instance like this:
var repo = RepositoryFactory.Resovle<IFullRepository>("connection string");
And the code that makes this work is here
public class RepositoryFactory
{
public static T Resovle<T>(string connection) where T: IRepository
{
IRepository instance = new Repository(connection);
return (T)instance;
}
private class Repository : IFullRepository
{
private string _connection;
public Repository(string connection)
{
_connection = connection;
}
public object Get(int id)
{
// select
}
public void Save(object o)
{
// upate
}
public void Create(object o)
{
// create
}
public void CustomMethodOne()
{
// do something specialized
}
public void CustomMethodTwo()
{
// do something specialized
}
}
}
public interface IRepository
{
object Get(int id);
void Save(object o);
void Create(object o);
}
public interface IRepositoryProjectOne: IRepository
{
void CustomMethodOne();
}
public interface IRepositoryProjectTwo: IRepository
{
void CustomMethodTwo();
}
public interface IFullRepository: IRepositoryProjectOne, IRepositoryProjectTwo
{
}
The downsides are, you get an explosion of Interfaces to control what methods are exposed. However, it is possible to cast between the various interfaces, but it avoids having to throw exceptions when a method isn't implemented.
There doesn't seem to be a perfect way to do this however I think your calling method needs to know whether or not it is allowed to write to the Repository as another poster has stated the availability of methods is something that needs to be known at compile time rather than run time.
The solution would be to create two interfaces, one that offers full functionality and one that offers limited functionality.
public interface IRepository : IRead
{
void Write(object o);
}
public interface IRead
{
object Read();
}
Your Repository object then implements the top interface.
public class Repository : IRepository
{
private readonly string _connectionString;
public Repository(string connectionString)
{
_connectionString = connectionString;
}
public object Read()
{
// Do stuff
}
public void Write(object o)
{
// Do stuff
}
}
You can then have a class that determines if the connection string demands a read only repository or not and exposes 2 different methods to return the given type of interface (meaning you need to know the type at compile time).
public static class RepositoryFactory
{
public static bool ConnectionStringIsReadOnly(string connectionString)
{
return connectionString.Contains("user=hacker");
}
public static IRead GetReadOnlyRepository(string connectionString)
{
return new Repository(connectionString);
}
public static IRepository GetRepository(string connectionString)
{
if (ConnectionStringIsReadOnly(connectionString)) throw new ArgumentException(#"Given connectionString is not allowed full repository access", "connectionString");
return new Repository(connectionString);
}
}
You can then consume this as follows, seperating the points where you try to do actions that require full access by checking that you have a version of IRepository or of IRead only.
public class Program
{
public void ConsumeRepository(string connectionString)
{
IRead reader = null;
IRepository repository = null;
if (RepositoryFactory.ConnectionStringIsReadOnly(connectionString))
reader = RepositoryFactory.GetReadOnlyRepository(connectionString);
else
{
repository = RepositoryFactory.GetRepository(connectionString);
reader = repository;
}
object o = reader.Read();
// do something with o
// if allowed then write o to repository
if (repository != null)
{
repository.Write(o);
}
}
}

Generics: How to check the exact type of T, without object for T

How can i check/evaluate the exact type of T without an object for T. I know my question maybe confusing but consider this...
public abstract class Business
{
public abstract string GetBusinessName();
}
public class Casino : Business
{
public override string GetBusinessName()
{
return "Casino Corp";
}
}
public class DrugStore : Business
{
public override string GetBusinessName()
{
return "DrugStore business";
}
}
public class BusinessManager<T> where T : Business
{
private Casino _casino;
private DrugStore _drugStore;
public string ShowBusinessName()
{
string businessName;
if (T == Casino) // Error: How can I check the type?
{
_casino = new Casino();
businessName = _casino.GetBusinessName();
}
else if (T == DrugStore) // Error: How can I check the type?
{
_drugStore = new DrugStore();
businessName = _drugStore.GetBusinessName();
}
return businessName;
}
}
I just want to have something like this on the client.
protected void Page_Load(object sender, EventArgs e)
{
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
businessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
}
Notice that I actually didnt create the actual object for Casino and Drugstore when I call the BusinessManager, I just pass it as generic type constraint of the class. I just need to know exactly what Type i am passing BusinessManager to know what exactly the Type to instantiate. Thanks...
PS: I don't want to create separate specific BusinessManager for Casino and Drugstore..
You can also comment about the design.. thanks..
ADDITIONAL: and what if class Casino and DrugStore is an ABSTRACT CLASS =)
You can write
if(typeof(T) == typeof(Casino))
but really this type of logic is a code smell.
Here's one way around this:
public class BusinessManager<T> where T : Business, new() {
private readonly T business;
public BusinessManager() {
business = new T();
}
}
but personally I'd prefer
public class BusinessManager<T> where T : Business {
private readonly T business;
public BusinessManager(T business) {
this.business = business;
}
public string GetBusinessName() {
return this.business.GetBusinessName();
}
}
You should do
public class BusinessManager<T> where T : Business, new()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
I don't know about C# syntax, but is it not possible to do:
public class BusinessManager<T> where T : Business, new()
{
private T _business;
public string ShowBusinessName()
{
string businessName;
_business = new T();
return _business.GetBusinessName();
}
}
Since other guys have already shown various answers to your first question, I would like to address the second one: design.
1. Role of BusinessManager
Actual role of the BusinessManager class in your example is not too clear. Since this class is generic, and it shouldn't be concerned with the actual type of T, then it does nothing more than add another unnecessary layer between the Business class and the rest of the program.
In other words, you can simply use:
Business casino = new Casino();
Response.Write(casino.GetBusinessName());
Business drugStore = new DrugStore();
Response.Write(drugStore.GetBusinessName());
Wrapping this in another generic class doesn't help you a lot. On the other hand, if you want to have some common functionality for all these classes, you can either add it directly to your abstract class, or extract an interface and create extension methods for that interface.
2. Using properties for getters
Second thing, using a property is more appropriate when you have a simple getter method. In other words, you should replace GetBusinessName() method with a Name property (I also omitted the "Business" from the name because it is not necessary:
public interface IBusiness
{
string Name { get; }
}
public abstract class Business : IBusiness
{
public abstract string Name { get; }
}
public class Casino : Business
{
public override string Name
{
get { return "Casino Corp"; }
}
}
public class DrugStore : Business
{
public override string Name
{
get { return "DrugStore business"; }
}
}
And then you can use it like this:
IBusiness casino = new Casino();
Response.Write(casino.Name);
IBusiness drugStore = new DrugStore();
Response.Write(drugStore.Name);
Also, you can see that I have introduced a IBusiness interface. The reason for doing so is to allow you to implement this interface in more diverse ways. Right now, you will try to derive all your classes from the abstract Business class, and try to extract as much of the common functionality in the abstract class (that's the purpose of the class).
But extracting lots of common functionality comes with a cost: there is always a possibility that you will come up with a need to create a class which isn't derived from Business. If you are accessing all these methods through the IBusiness interface, then other parts of your program won't care if that implementation is derived from Business or not.
Since GetBusinessName really applies to the type and not instances of the type, you might consider using DescriptionAttribute (or your own BusinessNameAttribute) instead of an overridden property and have your BusinessManager get the business name from the attribute.
[Description("Casino Corp")]
public class Casino : Business
{
}
Now you no longer need to instantiate the business just to gets its name. To get the description, you use:
public string ShowBusinessName()
{
var attribute = Attribute.GetCustomAttribute(typeof(T), typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute == null)
return "Unknown business";
return attribute.Description;
}
You can do something like this:
if (typeof(T) == typeof(SomeType))
{
// Same
}
define a BusinessManager class as bellow:
public class BusinessManager<T> where T : Business
{
Business biz;
public BusinessManager()
{
biz = new T();
}
public string ShowBusinessName()
{
return biz.GetBusinessName();
}
}
and use it as bellow:
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
var anotherBusinessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
The way you using you will lost encapsulation
In VB.net you can use the GetType pseudo-function on a generic type parameter to get a reflection Type object. I would guess C# should have an equivalent. If for whatever reason you can't use something like that, you could create an array of 0 elements of the desired type, and then check the type of that array. That would probably be cheaper than instantiating an element of the unknown type.

Categories