Generic type with parametherized constructor

A

Andrus

I need to create instance of generic type when generic type does not
have parameterless constructor.

I tried code below but got error shown in comment.
How to fix ?

Andrus.

abstract class QueryFactory<TEntity> {
public string O1;
public QueryFactory(string o1) {
O1 = o1;
}
}

class CustomerQueryFactory : QueryFactory<Customer> {
public CustomerQueryFactory(string o1) : base(o1) { }
}

class DocumentForm<TEntity, TQueryFactory>
where TQueryFactory : QueryFactory<TEntity> {

public DocumentForm() {
// Cannot create an instance of the variable type 'TQueryFactory'
// because it does not have the new() constraint
var x = new TQueryFactory("special parameter created in this method");
}
}

class Customer {
string Id { get; set; }
string Name { get; set; }
}

class Test {

static void Main() {
var x = new DocumentForm<Customer, CustomerQueryFactory>();
}
}
 
C

Clint

The underlying problem is "'TQueryFactory': cannot provide arguments when
creating an instance of a variable type"

So....

Replace:
var x = new TQueryFactory("special parameter created in this method");

With: (btw - I did it in 2005 so couldn't test with 'var')
TQueryFactory x = (TQueryFactory)typeof(TQueryFactory).GetConstructor(new
System.Type[] { typeof(string) }).Invoke(new object[] { "special parameter
created in this method" });


Hope that is what you are looking for. Apologies if I have it all wrong,
it's time to go home and I'm outahere...
If there is a better way, let me know.

Cheers.
 
A

Andrus

TQueryFactory x = (TQueryFactory)typeof(TQueryFactory).GetConstructor(new
System.Type[] { typeof(string) }).Invoke(new object[] { "special parameter
created in this method" });

Thay you very much. It works.
How to invoke TQueryFactory constructor in type-safe way ?
Is this C# design flaw ?

Andrus.
 
L

Lasse Vågsæther Karlsen

Andrus said:
TQueryFactory x = (TQueryFactory)typeof(TQueryFactory).GetConstructor(new
System.Type[] { typeof(string) }).Invoke(new object[] { "special parameter
created in this method" });

Thay you very much. It works.
How to invoke TQueryFactory constructor in type-safe way ?
Is this C# design flaw ?

Andrus.

Well, you could say that, but then, if a generic container had a
restriction to only allow generic types that had a constructor that took
a string parameter, what exactly would you do?

You could use it with:

- something that takes the name of an employee as a parameter
- something that takes the name of a property as a parameter
- something that takes a filename as a parameter

The likely common usage you would get out of this would not be very high.

At least that's my opinion. No doubt people might have scenarios which
would make sense, but your response is "but I know I will only use this
and that type", then my response to that would be to create descendants
of your container that knew about those specifics.
 
M

Marc Gravell

For info, I've got some "Type" extension methods in MiscUtil that
provide compiled (i.e. faster) access to Func<...> delegates to do
precisely this...

They aren't listed on the overview page, but they are there... IIRC, it
allows you to do things like someType.Ctor(4, "abc", 12) etc...

http://www.pobox.com/~skeet/csharp/miscutil/

Marc
 
A

Andrus

For info, I've got some "Type" extension methods in MiscUtil that provide
compiled (i.e. faster) access to Func<...> delegates to do precisely
this...

They aren't listed on the overview page, but they are there... IIRC, it
allows you to do things like someType.Ctor(4, "abc", 12) etc...

http://www.pobox.com/~skeet/csharp/miscutil/

I tried
TQueryFactory qm = typeof(TQueryFactory).Ctor(DataBase, Ko);

but got compile error

No overload for method 'Ctor' takes '2' arguments

Andrus.
 
M

Marc Gravell

First you need to get the delegate, and ideally stow it somewhere and
re-use it; I guess I could change the code to cache this internally
without any real problems...

Marc

using System;
using MiscUtil.Linq.Extensions;
interface IFoo
{
void Test();
}

class Bar : IFoo
{
private string message;
public Bar(string message)
{
this.message = message;
}
public void Test()
{
Console.WriteLine(message);
}
}

class Program
{
static void Main()
{
// perhaps loaded dynamically, etc
Type type = typeof(Bar);

// find the ctor that accepts a string, and
// return the new object as an IFoo (since
// we might not know about Bar at compile-time
// in a plugin/factory/IOC/DI model, etc)
Func<string, IFoo> ctor = type.Ctor<string, IFoo>();

IFoo foo = ctor("Does it work?");
foo.Test();
}
}
 
A

Andrus

Marc,
First you need to get the delegate, and ideally stow it somewhere and
re-use it; I guess I could change the code to cache this internally
without any real problems...

Thank you. It works.
I'm wondering where there is no method for single-line constructor call.

Andrus.
 
M

Marc Gravell

If the Type arg was a generic type argument, it would be trivial to
implement (via a generic cache-class); as it is, I'd need some kind of
lookup (Dictionary<Type, ...> or similar) - that is the only issue...
but you could simply take the source code and use it to make your own
implementation...

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top