Create empty list by type name

  • Thread starter Thread starter Andrus
  • Start date Start date
A

Andrus

I know entity class name as string ( e.q. "Customer" )

I need to create empty List<Customer> object for this entity by class name
passed as string in runtime.

I tried the following code but got compile error shown in comment.

How to create empty list based on type ?
I hope some reflection method can be used for this ?

Sidenote:

I need to use type t for list creation since my data binding looks for
property names which are different in every entity.
This list is used as DataGridViewComboBoxCell DataSource and filled
dynamically in DataGridView OnDataError event.
I know it is possible to add a method returning empty list for every
entity class by I'm looking for a solution which does to require new method
in every entity class.

Andrus.


Codo to show the problem:

using System.Collections.Generic;
using System;

class TestApplication {

static void Main() {
object CustomerColumnDynamicDataSource =
CreateEmptyListByTypeName("Customer");
object ProductColumnDynamicDataSource =
CreateEmptyListByTypeName("Product");
}

static IList<object> CreateEmptyListByTypeName(string typeName) {
Type t = Type.GetType(typeName);

//Next line causes error:
// The type or namespace name 't' could not be found (are you missing a
//using directive or an assembly reference?)
return (IList<object>)new List<t>();
}
}

class Customer : ActiveRecordBase<Customer> { }

class Product : ActiveRecordBase<Product> { }

public class ActiveRecordBase<T> {}
 
Andrus,

You will want to look at the MakeGenericType method on the Type class.
The thing is, you will have to use late binding in order to access the list
you create, as you won't be able to cast it to IList<object>.

A better solution is to generate a base type or interface that all of
your types implement, and then create List<> of those.
 
Thank you.

My business objects have different properties.
So it is not possible to create base type or interface.
I have no experience creating generic type.

So I found best solution to change my business object class code generator
to add
method GetEmptyList() to every generated class.
However casting it to List<object> causes runtime error since C# does not
yet
support covariant types.

How to fix it ?

Code to show the issue:

using System.Collections.Generic;
using System;
using System.Reflection;

class TestApplication {

static void Main() {
object l1 = CreateEmptyListByTypeName("Customer");
object l2 = CreateEmptyListByTypeName("Product");
}

static IList<object> CreateEmptyListByTypeName(string typeName) {

Type type = Type.GetType(typeName);
MethodInfo methodInfo = type.GetMethod("GetEmptyList",
BindingFlags.Public | BindingFlags.FlattenHierarchy |
BindingFlags.Static, null, Type.EmptyTypes, null);

// System.InvalidCastException was unhandled
//Unable to cast object of type
// 'System.Collections.Generic.List`1[Customer]' to
// type 'System.Collections.Generic.IList`1[System.Object]'."
return (IList<object>)methodInfo.Invoke(null, null);
}
}

class Customer : ActiveRecordBase<Customer> {

public static List<Customer> GetEmptyList() {
return new List<Customer>();
}
}

class Product : ActiveRecordBase<Product> {

public static List<Product> GetEmptyList() {
return new List<Product>();
}

}

public class ActiveRecordBase<T> {

}



Andrus,

You will want to look at the MakeGenericType method on the Type class.
The thing is, you will have to use late binding in order to access the
list you create, as you won't be able to cast it to IList<object>.

A better solution is to generate a base type or interface that all of
your types implement, and then create List<> of those.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Andrus said:
I know entity class name as string ( e.q. "Customer" )

I need to create empty List<Customer> object for this entity by class
name
passed as string in runtime.

I tried the following code but got compile error shown in comment.

How to create empty list based on type ?
I hope some reflection method can be used for this ?

Sidenote:

I need to use type t for list creation since my data binding looks for
property names which are different in every entity.
This list is used as DataGridViewComboBoxCell DataSource and filled
dynamically in DataGridView OnDataError event.
I know it is possible to add a method returning empty list for every
entity class by I'm looking for a solution which does to require new
method
in every entity class.

Andrus.


Codo to show the problem:

using System.Collections.Generic;
using System;

class TestApplication {

static void Main() {
object CustomerColumnDynamicDataSource =
CreateEmptyListByTypeName("Customer");
object ProductColumnDynamicDataSource =
CreateEmptyListByTypeName("Product");
}

static IList<object> CreateEmptyListByTypeName(string typeName) {
Type t = Type.GetType(typeName);

//Next line causes error:
// The type or namespace name 't' could not be found (are you missing a
//using directive or an assembly reference?)
return (IList<object>)new List<t>();
}
}

class Customer : ActiveRecordBase<Customer> { }

class Product : ActiveRecordBase<Product> { }

public class ActiveRecordBase<T> {}
 
Andrus,

Because generics do not support covariance, you have to derive all of
your objects from a base type, even if they don't share properties (you can
have a type with no properties that they derive from) and then return that.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Andrus said:
Thank you.

My business objects have different properties.
So it is not possible to create base type or interface.
I have no experience creating generic type.

So I found best solution to change my business object class code generator
to add
method GetEmptyList() to every generated class.
However casting it to List<object> causes runtime error since C# does not
yet
support covariant types.

How to fix it ?

Code to show the issue:

using System.Collections.Generic;
using System;
using System.Reflection;

class TestApplication {

static void Main() {
object l1 = CreateEmptyListByTypeName("Customer");
object l2 = CreateEmptyListByTypeName("Product");
}

static IList<object> CreateEmptyListByTypeName(string typeName) {

Type type = Type.GetType(typeName);
MethodInfo methodInfo = type.GetMethod("GetEmptyList",
BindingFlags.Public | BindingFlags.FlattenHierarchy |
BindingFlags.Static, null, Type.EmptyTypes, null);

// System.InvalidCastException was unhandled
//Unable to cast object of type
// 'System.Collections.Generic.List`1[Customer]' to
// type 'System.Collections.Generic.IList`1[System.Object]'."
return (IList<object>)methodInfo.Invoke(null, null);
}
}

class Customer : ActiveRecordBase<Customer> {

public static List<Customer> GetEmptyList() {
return new List<Customer>();
}
}

class Product : ActiveRecordBase<Product> {

public static List<Product> GetEmptyList() {
return new List<Product>();
}

}

public class ActiveRecordBase<T> {

}



"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
kirjutas
sõnumis
Andrus,

You will want to look at the MakeGenericType method on the Type class.
The thing is, you will have to use late binding in order to access the
list you create, as you won't be able to cast it to IList<object>.

A better solution is to generate a base type or interface that all of
your types implement, and then create List<> of those.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Andrus said:
I know entity class name as string ( e.q. "Customer" )

I need to create empty List<Customer> object for this entity by class
name
passed as string in runtime.

I tried the following code but got compile error shown in comment.

How to create empty list based on type ?
I hope some reflection method can be used for this ?

Sidenote:

I need to use type t for list creation since my data binding looks for
property names which are different in every entity.
This list is used as DataGridViewComboBoxCell DataSource and filled
dynamically in DataGridView OnDataError event.
I know it is possible to add a method returning empty list for every
entity class by I'm looking for a solution which does to require new
method
in every entity class.

Andrus.


Codo to show the problem:

using System.Collections.Generic;
using System;

class TestApplication {

static void Main() {
object CustomerColumnDynamicDataSource =
CreateEmptyListByTypeName("Customer");
object ProductColumnDynamicDataSource =
CreateEmptyListByTypeName("Product");
}

static IList<object> CreateEmptyListByTypeName(string typeName) {
Type t = Type.GetType(typeName);

//Next line causes error:
// The type or namespace name 't' could not be found (are you missing a
//using directive or an assembly reference?)
return (IList<object>)new List<t>();
}
}

class Customer : ActiveRecordBase<Customer> { }

class Product : ActiveRecordBase<Product> { }

public class ActiveRecordBase<T> {}
 
So I must change those types to object.

Can I assume that ComboBox binding examines Datasource type at runtime ?
Can I assume that if it finds it to be based on IList<mybusinessobject> it
uses mybusinessobject properies for Display and Value members ?

Andrus.

Nicholas Paldino said:
Andrus,

Because generics do not support covariance, you have to derive all of
your objects from a base type, even if they don't share properties (you
can have a type with no properties that they derive from) and then return
that.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Andrus said:
Thank you.

My business objects have different properties.
So it is not possible to create base type or interface.
I have no experience creating generic type.

So I found best solution to change my business object class code
generator to add
method GetEmptyList() to every generated class.
However casting it to List<object> causes runtime error since C# does not
yet
support covariant types.

How to fix it ?

Code to show the issue:

using System.Collections.Generic;
using System;
using System.Reflection;

class TestApplication {

static void Main() {
object l1 = CreateEmptyListByTypeName("Customer");
object l2 = CreateEmptyListByTypeName("Product");
}

static IList<object> CreateEmptyListByTypeName(string typeName) {

Type type = Type.GetType(typeName);
MethodInfo methodInfo = type.GetMethod("GetEmptyList",
BindingFlags.Public | BindingFlags.FlattenHierarchy |
BindingFlags.Static, null, Type.EmptyTypes, null);

// System.InvalidCastException was unhandled
//Unable to cast object of type
// 'System.Collections.Generic.List`1[Customer]' to
// type 'System.Collections.Generic.IList`1[System.Object]'."
return (IList<object>)methodInfo.Invoke(null, null);
}
}

class Customer : ActiveRecordBase<Customer> {

public static List<Customer> GetEmptyList() {
return new List<Customer>();
}
}

class Product : ActiveRecordBase<Product> {

public static List<Product> GetEmptyList() {
return new List<Product>();
}

}

public class ActiveRecordBase<T> {

}



"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
kirjutas
sõnumis
Andrus,

You will want to look at the MakeGenericType method on the Type
class.
The thing is, you will have to use late binding in order to access the
list you create, as you won't be able to cast it to IList<object>.

A better solution is to generate a base type or interface that all of
your types implement, and then create List<> of those.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I know entity class name as string ( e.q. "Customer" )

I need to create empty List<Customer> object for this entity by class
name
passed as string in runtime.

I tried the following code but got compile error shown in comment.

How to create empty list based on type ?
I hope some reflection method can be used for this ?

Sidenote:

I need to use type t for list creation since my data binding looks for
property names which are different in every entity.
This list is used as DataGridViewComboBoxCell DataSource and filled
dynamically in DataGridView OnDataError event.
I know it is possible to add a method returning empty list for every
entity class by I'm looking for a solution which does to require new
method
in every entity class.

Andrus.


Codo to show the problem:

using System.Collections.Generic;
using System;

class TestApplication {

static void Main() {
object CustomerColumnDynamicDataSource =
CreateEmptyListByTypeName("Customer");
object ProductColumnDynamicDataSource =
CreateEmptyListByTypeName("Product");
}

static IList<object> CreateEmptyListByTypeName(string typeName) {
Type t = Type.GetType(typeName);

//Next line causes error:
// The type or namespace name 't' could not be found (are you missing a
//using directive or an assembly reference?)
return (IList<object>)new List<t>();
}
}

class Customer : ActiveRecordBase<Customer> { }

class Product : ActiveRecordBase<Product> { }

public class ActiveRecordBase<T> {}
 
Back
Top