2

I have a Generic class like this :

public class Mapper<TEntity, TDataAccess>
    where TEntity : Common.IEntity
    where TDataAccess : DataAccess, new()
{
    public TDataAccess DataAccess { get; set; } 
    public Mapper()
    {
        DataAccess = new TDataAccess();
    }
    /*
     * ...
     * */
}

and data access is like this :

public class DataAccess
{
    public DataAccess()
    {}

    public DataAccess(string tranName)
    {}

    // CRUD functionality and other data access staff
}

and a inherited class form DataAccess :

public class UserDataAccess:DataAccess
{
    public UserDataAccess():base(string.Empty)
    {
    }
    public UserDataAccess(string tranName):base(tranName)
    {
        // Something to do with user
    }
}

and finally UserMapper from Mapper :

public class UserMapper : Mapper<User,UserDataAccess>
{
    // Mapping entity properties with datarows columns
}

now imagine that I need to send tranName to given TDataAccess in UserMapper. how can do this without changing DataAccess class ? I can't access the source of DataAccess and also Generics don't realize Types different constructor overloads. I know that I can have a property on UserDataAccess and fill it whenever I need, but I can't because of thread safety issue.

The User class is a plain entity - it has only properties.

2 Answers 2

3

As a case you can use overload of the Activator.CreateInstance() method by specifying constructor parameter:

var dataAccess = Activator.CreateInstance(
                            typeof(TDataAccess), 
                            new object[] { tranName });

MSDN:

public static Object CreateInstance(
    Type type,
    params Object[] args
)

Creates an instance of the specified type using the constructor that best matches the specified parameters.

Sign up to request clarification or add additional context in comments.

Comments

2

Generics does not support that. Options:

  • have a protected virtual TDataAccess CreateDataAccess() method, that by default uses new TDataAccess(), but which can be overridden by UserMapper to create the object any way it likes; call CreateDataAccess() instead of new TDataAccess()
  • pass in a factory method as a delegate, i.e. a Func<TDataAccess> - so the caller could supply () => new DataAccess("foo"), and use that instead of the new TDataAccess()
  • use reflection-based code to create the TDataAccess - either Activator.CreateInstance (which supports parameters), or something involving meta-programming (Expression, ILGenerator, etc)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.