Create new T, X and populate class using reflections C# [duplicate] - c#

While mapping class i am getting error 'T' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method.
Below is my SqlReaderBase Class
public abstract class SqlReaderBase<T> : ConnectionProvider
{
#region Abstract Methods
protected abstract string commandText { get; }
protected abstract CommandType commandType { get; }
protected abstract Collection<IDataParameter> GetParameters(IDbCommand command);
**protected abstract MapperBase<T> GetMapper();**
#endregion
#region Non Abstract Methods
/// <summary>
/// Method to Execute Select Queries for Retrieveing List of Result
/// </summary>
/// <returns></returns>
public Collection<T> ExecuteReader()
{
//Collection of Type on which Template is applied
Collection<T> collection = new Collection<T>();
// initializing connection
using (IDbConnection connection = GetConnection())
{
try
{
// creates command for sql operations
IDbCommand command = connection.CreateCommand();
// assign connection to command
command.Connection = connection;
// assign query
command.CommandText = commandText;
//state what type of query is used, text, table or Sp
command.CommandType = commandType;
// retrieves parameter from IDataParameter Collection and assigns it to command object
foreach (IDataParameter param in GetParameters(command))
command.Parameters.Add(param);
// Establishes connection with database server
connection.Open();
// Since it is designed for executing Select statements that will return a list of results
// so we will call command's execute reader method that return a Forward Only reader with
// list of results inside.
using (IDataReader reader = command.ExecuteReader())
{
try
{
// Call to Mapper Class of the template to map the data to its
// respective fields
MapperBase<T> mapper = GetMapper();
collection = mapper.MapAll(reader);
}
catch (Exception ex) // catch exception
{
throw ex; // log errr
}
finally
{
reader.Close();
reader.Dispose();
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
connection.Close();
connection.Dispose();
}
}
return collection;
}
#endregion
}
What I am trying to do is , I am executine some command and filling my class dynamically. The class is given below:
namespace FooZo.Core
{
public class Restaurant
{
#region Private Member Variables
private int _restaurantId = 0;
private string _email = string.Empty;
private string _website = string.Empty;
private string _name = string.Empty;
private string _address = string.Empty;
private string _phone = string.Empty;
private bool _hasMenu = false;
private string _menuImagePath = string.Empty;
private int _cuisine = 0;
private bool _hasBar = false;
private bool _hasHomeDelivery = false;
private bool _hasDineIn = false;
private int _type = 0;
private string _restaurantImagePath = string.Empty;
private string _serviceAvailableTill = string.Empty;
private string _serviceAvailableFrom = string.Empty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Address
{
get { return _address; }
set { _address = value; }
}
public int RestaurantId
{
get { return _restaurantId; }
set { _restaurantId = value; }
}
public string Website
{
get { return _website; }
set { _website = value; }
}
public string Email
{
get { return _email; }
set { _email = value; }
}
public string Phone
{
get { return _phone; }
set { _phone = value; }
}
public bool HasMenu
{
get { return _hasMenu; }
set { _hasMenu = value; }
}
public string MenuImagePath
{
get { return _menuImagePath; }
set { _menuImagePath = value; }
}
public string RestaurantImagePath
{
get { return _restaurantImagePath; }
set { _restaurantImagePath = value; }
}
public int Type
{
get { return _type; }
set { _type = value; }
}
public int Cuisine
{
get { return _cuisine; }
set { _cuisine = value; }
}
public bool HasBar
{
get { return _hasBar; }
set { _hasBar = value; }
}
public bool HasHomeDelivery
{
get { return _hasHomeDelivery; }
set { _hasHomeDelivery = value; }
}
public bool HasDineIn
{
get { return _hasDineIn; }
set { _hasDineIn = value; }
}
public string ServiceAvailableFrom
{
get { return _serviceAvailableFrom; }
set { _serviceAvailableFrom = value; }
}
public string ServiceAvailableTill
{
get { return _serviceAvailableTill; }
set { _serviceAvailableTill = value; }
}
#endregion
public Restaurant() { }
}
}
For filling my class properties dynamically i have another class called MapperBase Class with following methods:
public abstract class MapperBase<T> where T : new()
{
protected T Map(IDataRecord record)
{
T instance = new T();
string fieldName;
PropertyInfo[] properties = typeof(T).GetProperties();
for (int i = 0; i < record.FieldCount; i++)
{
fieldName = record.GetName(i);
foreach (PropertyInfo property in properties)
{
if (property.Name == fieldName)
{
property.SetValue(instance, record[i], null);
}
}
}
return instance;
}
public Collection<T> MapAll(IDataReader reader)
{
Collection<T> collection = new Collection<T>();
while (reader.Read())
{
collection.Add(Map(reader));
}
return collection;
}
}
There is another class which inherits the SqlreaderBaseClass called DefaultSearch. Code is below
public class DefaultSearch: SqlReaderBase<Restaurant>
{
protected override string commandText
{
get { return "Select Name from vw_Restaurants"; }
}
protected override CommandType commandType
{
get { return CommandType.Text; }
}
protected override Collection<IDataParameter> GetParameters(IDbCommand command)
{
Collection<IDataParameter> parameters = new Collection<IDataParameter>();
parameters.Clear();
return parameters;
}
protected override MapperBase<Restaurant> GetMapper()
{
MapperBase<Restaurant> mapper = new RMapper();
return mapper;
}
}
But whenever I tried to build , I am getting error 'T' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method. Even T here is Restaurant has a Parameterless Public constructor.

The problem is that you're trying to use the T from SqlReaderBase as the type argument for MapperBase - but you don't have any constraints on that T.
Try changing your SqlReaderBase declaration to this:
public abstract class SqlReaderBase<T> : ConnectionProvider
where T : new()
Here's a shorter example which demonstrates the same issue:
class Foo<T>
{
Bar<T> bar;
}
class Bar<T> where T : new()
{
}
The fix is to change Foo<T>'s declaration to:
class Foo<T> where T : new()
Then the compiler will know that the T from Foo is a valid type argument for Bar.

The constraints must apply to every type in the chain; hence you need:
public abstract class SqlReaderBase<T> : ConnectionProvider where T : new()
Without this, you can't satisfy the constraint for T in:
protected abstract MapperBase<T> GetMapper();
or
MapperBase<T> mapper = GetMapper();
since MapperBase<> is only usable when T has : new()

I had the same issue. I should have read the message before Googling it. I needed to add a parameterless constructor ... :-)
public MyClass() {
//stuff
}

Related

Protobuf-net Serializing Parent Class inherited object property marked as [ProtoIgnore()] throwing "No serializer defined for type: System.Object"

All the objects in our system inherit a base class which has got a property of type object.
I have tried adding protoignore attribute to all the properties of the base class as well but that doesn't seem to work as well.
class Program
{
static void Main(string[] args)
{
Vehicle vehicle = new Vehicle();
vehicle.BodyStyleDescription = "4x4";
vehicle.BodyStyleText = "Prestige Medium";
dynamic protobufModel = TypeModel.Create();
AddTypeToModel<Vehicle>(protobufModel);
using (MemoryStream compressed = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(compressed, CompressionMode.Compress, true))
{
protobufModel.Serialize(gzip, vehicle);
}
string str = Convert.ToBase64String(compressed.GetBuffer(), 0, Convert.ToInt32(compressed.Length));
}
}
public static MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
{
var properties = typeof(T).GetProperties().Select(p => p.Name).OrderBy(name => name);
return typeModel.Add(typeof(T), true).Add(properties.ToArray());
}
}
Following is the hierarchy of the object
public interface IObjectBaseClass
{
[ProtoIgnore()]
object Parent { get; set; }
[ProtoIgnore()]
bool IsSaved { get; set; }
[ProtoIgnore()]
string XmlAtLoad { get; set; }
}
public class ObjectBaseClass : IObjectBaseClass
{
public ObjectBaseClass()
{
}
[ProtoIgnore()]
internal object _Parent;
[ProtoIgnore()]
internal bool _IsSaved;
[ProtoIgnore()]
internal string _XmlAtLoad;
[ProtoIgnore()]
public bool IsSaved
{
get { return _IsSaved; }
set { _IsSaved = value; }
}
[ProtoIgnore()]
public object Parent
{
get { return _Parent; }
set { _Parent = value; }
}
[ProtoIgnore()]
public string XmlAtLoad
{
get { return _XmlAtLoad; }
set { _XmlAtLoad = value; }
}
}
public class Vehicle : ObjectBaseClass
{
private string _BodyStyleText;
private string _BodyStyleDescription;
public string BodyStyleDescription
{
get { return _BodyStyleDescription; }
set { _BodyStyleDescription = value; }
}
public string BodyStyleText
{
get { return _BodyStyleText; }
set { _BodyStyleText = value; }
}
}
Your problem is that when you do typeModel.Add(typeof(T), true).Add(properties.ToArray()) you are adding all properties of T to the runtime type model, including those marked with ProtoIgnore. You can see this by calling the debugging method protobufModel.GetSchema(typeof(Vehicle)) which returns:
message Object {
}
message Vehicle {
optional string BodyStyleDescription = 1;
optional string BodyStyleText = 2;
optional bool IsSaved = 3;
optional Object Parent = 4;
optional string XmlAtLoad = 5;
}
To avoid adding properties marked with [ProtoIgnore], you could do:
public static MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
{
var properties = typeof(T)
.GetProperties()
.Where(p => !p.GetCustomAttributes<ProtoIgnoreAttribute>().Any())
.Select(p => p.Name)
.OrderBy(name => name);
return typeModel.Add(typeof(T), true).Add(properties.ToArray());
}
Alternatively, since you are manually annotating some of your models with protobuf attributes anyway, you could mark the derived types with [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)], e.g.:
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Vehicle : ObjectBaseClass
{
private string _BodyStyleText;
private string _BodyStyleDescription;
public string BodyStyleDescription
{
get { return _BodyStyleDescription; }
set { _BodyStyleDescription = value; }
}
public string BodyStyleText
{
get { return _BodyStyleText; }
set { _BodyStyleText = value; }
}
}
Using either method, the schema for Vehicle becomes:
message Vehicle {
optional string BodyStyleDescription = 1;
optional string BodyStyleText = 2;
}
This is what you require.

Make my Type work like a list

I have created a list of my own type... (Classes for custom types at bottom of page)
List<gridRecord> lgr = new List<gridRecord>();
lgr = populatedList();
I validate each field in the List with the code bellow... (This works fine!)
foreach (gridRecord gr in lgr)
{
gr.Quantity.validate();
gr.Title.validate();
gr.Pages.validate();
dt.Rows.Add(gr.Title.Value.ToString(), gr.Quantity.Value.ToString(), gr.Pages.Value.ToString());
}
However I will be adding new gridFields to the gridRecord Class, and do not want to change the code that is validating.
so...I would like to be able to do something like this...
foreach (gridField gf in lgr)
{
gf.Validate();
}
grid Record Class...
class gridRecord : Validateit
{
//Constructor
public gridRecord()
{
Quantity = new quantityField();
Title = new titleField();
Pages = new pagesField();
}
private quantityField quantity;
private titleField title;
private pagesField pages;
public quantityField Quantity
{
get { return quantity; }
set { quantity = value; }
}
public titleField Title
{
get { return title; }
set { title = value; }
}
public pagesField Pages
{
get { return pages; }
set { pages = value; }
}
public override void Validate()
{
}
}
gridField Class...
class gridField : Validateit
{
public gridField()
{
Value = "---";
isValid = false;
message = "";
}
private string value;
protected bool isValid;
private string message;
public string Value
{
get { return this.value; }
set { this.value = value; }
}
public bool IsValid
{
get { return isValid; }
set { isValid = value; }
}
public string Message
{
get { return message; }
set { message = value; }
}
public override void Validate()
{
}
}
do I need to use IEnumerable if so how?
Thanks
If you want code like this:
foreach (gridRecord gr in lgr)
{
gr.Validate();
}
It is a simple case of implementing what you need within that Validate method of gridRecord (BTW: That class should be named GridRecord - classes should start with an upper case character according to C# naming convention)
class gridRecord : Validateit
{
//.. snip
public override void Validate()
{
this.Quantity.Validate();
this.Title.Validate();
this.Pages.Validate();
}
}
If, however, you want to enumerate all the fields you can make each gridRecord implement IEnumerable<gridField> like this:
class gridRecord : Validateit, IEnumerable<gridField>
{
//.. snip
public IEnumerator<gridField> GetEnumerator()
{
yield return Quantity;
yield return Title;
yield return Pages;
}
public IEnumerator GetEnumerator()
{
return GetEnumerator(); // generic version
}
}
Then you can have code like this:
foreach (gridRecord gr in lgr) // enumerate each record
{
foreach(gridField gf in gr) // enumerate each field within each record
{
gf.Validate();
}
}

'XamlParseException' when saving lists using XmlSerializer

I'm trying to save two lists of my custom objects the first list of type List<Vechicle>.
XmlSerializer SerializerObjVechicle = new XmlSerializer(typeof(List<Vechicle>));
Then I get the error
"An unhandled exception of type
'System.Windows.Markup.XamlParseException' occurred in
PresentationFramework.dll"
This is my vechicle class
[Serializable]
public class Vechicle
{
private int _Id;
private String _Registration;
public Vechicle(int id,String registration)
{
Id = id;
Registration = registration;
}
public override string ToString()
{
return Id.ToString() + " " + Registration;
}
#region getters/setters
public int Id{
get { return _Id; }
set { _Id = value; }
}
public String Registration
{
get { return _Registration; }
set { _Registration = value; }
}
#endregion
}
}
bogza.anton's answer is right, you need to provide a constructor without parameters, I give a sample like this:
[Serializable]
public class Vechicle
{
private int _Id;
private String _Registration;
public Vechicle()
{
_Id = 1;
_Registration = "default name";
}
public Vechicle(int id, String registration)
{
Id = id;
Registration = registration;
}
public override string ToString()
{
return Id.ToString() + " " + Registration;
}
#region getters/setters
public int Id
{
get { return _Id; }
set { _Id = value; }
}
public String Registration
{
get { return _Registration; }
set { _Registration = value; }
}
#endregion
}
private void button1_Click(object sender, EventArgs e)
{
List<Vechicle> vList = new List<Vechicle>()
{
new Vechicle(),
new Vechicle(),
new Vechicle{Id=2, Registration="hello"},
new Vechicle{Id = 100, Registration="world"}
};
XmlSerializer SerializerObjVechicle = new XmlSerializer(vList.GetType());
FileStream fs = new FileStream("d:\\test.xml", FileMode.OpenOrCreate);
SerializerObjVechicle.Serialize(fs, vList);
}
result of my test is below:
Need to add a constructor without parameters.
Or inherit class from interface ISerializable.
http://msdn.microsoft.com/en-us/library/vstudio/ms233843(v=vs.110).aspx

C# Custom Data Converter for Reading Bytes[]

Here is my custom dataconverter helper class which helps me to read the value from DataReader and return
public class DataConvertor<T> where T : IhasIndexer
{
public DataConvertorField<string, T> String;
public DataConvertorField<int, T> Int;
T reader;
public void Initialise(T reader)
{
this.reader = reader;
String = new DataConvertorField<string, T>(reader, Convert.ToString);
Int = new DataConvertorField<int, T>(reader, Convert.ToInt32);
}
public bool has(string name)
{
try
{
object o = reader[name];
return true;
}
catch
{
return false;
}
}
}
public class DataConvertorField<T, O> where O : IhasIndexer
{
O parent;
DataConvertorMethod convertor;
public DataConvertorField(O parent, DataConvertorMethod convertor)
{
this.parent = parent;
this.convertor = convertor;
}
public T this[string name]
{
get
{
if (parent[name] == DBNull.Value)
{
if (typeof(T).Equals(typeof(string)))
return (T)(object)string.Empty;
else
return default(T);
}
else
return convertor(parent[name]);
}
}
public delegate T DataConvertorMethod(object o);
}
public interface IhasIndexer
{
object this[string key] { get; }
}
Then i simply use in my ADO.Net code as below
using (DBDataReaderWrapper reader = cmd.ExecuteReader())
{
while (reader.Read())
{
user.UserId = reader.Int["UserId"];
user.UserName = reader.String["UserName"];
}
public class DBDataReaderWrapper : DataConvertor<DBDataReaderWrapper>,
IDisposable, IhasIndexer
{
SqlDataReader reader;
public DBDataReaderWrapper(SqlDataReader reader)
{
Initialise(this);
this.reader = reader;
}
public object this[string name]
{
get
{
return reader[name];
}
}
public bool Read()
{
return reader.Read();
}
public bool NextResult()
{
return reader.NextResult();
}
public void Dispose()
{
reader.Close();
reader.Dispose();
}
}
}
The question is how can i use my helper class for reading image from Database. I want to add DataConverter like
public DataConvertorField<byte[], T> Bytes;
and in Initialise() method
Bytes = new DataConvertorField<byte[]>(reader, Convert.to??????);
How can i achieve this? any c# built in or helper method available for my need?
So i can use like in ADO.Net code
reader.Bytes["UserImage"]; //use custom data covertor and gives bytes[]

Class Mapping Error: 'T' must be a non-abstract type with a public parameterless constructor

While mapping class i am getting error 'T' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method.
Below is my SqlReaderBase Class
public abstract class SqlReaderBase<T> : ConnectionProvider
{
#region Abstract Methods
protected abstract string commandText { get; }
protected abstract CommandType commandType { get; }
protected abstract Collection<IDataParameter> GetParameters(IDbCommand command);
**protected abstract MapperBase<T> GetMapper();**
#endregion
#region Non Abstract Methods
/// <summary>
/// Method to Execute Select Queries for Retrieveing List of Result
/// </summary>
/// <returns></returns>
public Collection<T> ExecuteReader()
{
//Collection of Type on which Template is applied
Collection<T> collection = new Collection<T>();
// initializing connection
using (IDbConnection connection = GetConnection())
{
try
{
// creates command for sql operations
IDbCommand command = connection.CreateCommand();
// assign connection to command
command.Connection = connection;
// assign query
command.CommandText = commandText;
//state what type of query is used, text, table or Sp
command.CommandType = commandType;
// retrieves parameter from IDataParameter Collection and assigns it to command object
foreach (IDataParameter param in GetParameters(command))
command.Parameters.Add(param);
// Establishes connection with database server
connection.Open();
// Since it is designed for executing Select statements that will return a list of results
// so we will call command's execute reader method that return a Forward Only reader with
// list of results inside.
using (IDataReader reader = command.ExecuteReader())
{
try
{
// Call to Mapper Class of the template to map the data to its
// respective fields
MapperBase<T> mapper = GetMapper();
collection = mapper.MapAll(reader);
}
catch (Exception ex) // catch exception
{
throw ex; // log errr
}
finally
{
reader.Close();
reader.Dispose();
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
connection.Close();
connection.Dispose();
}
}
return collection;
}
#endregion
}
What I am trying to do is , I am executine some command and filling my class dynamically. The class is given below:
namespace FooZo.Core
{
public class Restaurant
{
#region Private Member Variables
private int _restaurantId = 0;
private string _email = string.Empty;
private string _website = string.Empty;
private string _name = string.Empty;
private string _address = string.Empty;
private string _phone = string.Empty;
private bool _hasMenu = false;
private string _menuImagePath = string.Empty;
private int _cuisine = 0;
private bool _hasBar = false;
private bool _hasHomeDelivery = false;
private bool _hasDineIn = false;
private int _type = 0;
private string _restaurantImagePath = string.Empty;
private string _serviceAvailableTill = string.Empty;
private string _serviceAvailableFrom = string.Empty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Address
{
get { return _address; }
set { _address = value; }
}
public int RestaurantId
{
get { return _restaurantId; }
set { _restaurantId = value; }
}
public string Website
{
get { return _website; }
set { _website = value; }
}
public string Email
{
get { return _email; }
set { _email = value; }
}
public string Phone
{
get { return _phone; }
set { _phone = value; }
}
public bool HasMenu
{
get { return _hasMenu; }
set { _hasMenu = value; }
}
public string MenuImagePath
{
get { return _menuImagePath; }
set { _menuImagePath = value; }
}
public string RestaurantImagePath
{
get { return _restaurantImagePath; }
set { _restaurantImagePath = value; }
}
public int Type
{
get { return _type; }
set { _type = value; }
}
public int Cuisine
{
get { return _cuisine; }
set { _cuisine = value; }
}
public bool HasBar
{
get { return _hasBar; }
set { _hasBar = value; }
}
public bool HasHomeDelivery
{
get { return _hasHomeDelivery; }
set { _hasHomeDelivery = value; }
}
public bool HasDineIn
{
get { return _hasDineIn; }
set { _hasDineIn = value; }
}
public string ServiceAvailableFrom
{
get { return _serviceAvailableFrom; }
set { _serviceAvailableFrom = value; }
}
public string ServiceAvailableTill
{
get { return _serviceAvailableTill; }
set { _serviceAvailableTill = value; }
}
#endregion
public Restaurant() { }
}
}
For filling my class properties dynamically i have another class called MapperBase Class with following methods:
public abstract class MapperBase<T> where T : new()
{
protected T Map(IDataRecord record)
{
T instance = new T();
string fieldName;
PropertyInfo[] properties = typeof(T).GetProperties();
for (int i = 0; i < record.FieldCount; i++)
{
fieldName = record.GetName(i);
foreach (PropertyInfo property in properties)
{
if (property.Name == fieldName)
{
property.SetValue(instance, record[i], null);
}
}
}
return instance;
}
public Collection<T> MapAll(IDataReader reader)
{
Collection<T> collection = new Collection<T>();
while (reader.Read())
{
collection.Add(Map(reader));
}
return collection;
}
}
There is another class which inherits the SqlreaderBaseClass called DefaultSearch. Code is below
public class DefaultSearch: SqlReaderBase<Restaurant>
{
protected override string commandText
{
get { return "Select Name from vw_Restaurants"; }
}
protected override CommandType commandType
{
get { return CommandType.Text; }
}
protected override Collection<IDataParameter> GetParameters(IDbCommand command)
{
Collection<IDataParameter> parameters = new Collection<IDataParameter>();
parameters.Clear();
return parameters;
}
protected override MapperBase<Restaurant> GetMapper()
{
MapperBase<Restaurant> mapper = new RMapper();
return mapper;
}
}
But whenever I tried to build , I am getting error 'T' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method. Even T here is Restaurant has a Parameterless Public constructor.
The problem is that you're trying to use the T from SqlReaderBase as the type argument for MapperBase - but you don't have any constraints on that T.
Try changing your SqlReaderBase declaration to this:
public abstract class SqlReaderBase<T> : ConnectionProvider
where T : new()
Here's a shorter example which demonstrates the same issue:
class Foo<T>
{
Bar<T> bar;
}
class Bar<T> where T : new()
{
}
The fix is to change Foo<T>'s declaration to:
class Foo<T> where T : new()
Then the compiler will know that the T from Foo is a valid type argument for Bar.
The constraints must apply to every type in the chain; hence you need:
public abstract class SqlReaderBase<T> : ConnectionProvider where T : new()
Without this, you can't satisfy the constraint for T in:
protected abstract MapperBase<T> GetMapper();
or
MapperBase<T> mapper = GetMapper();
since MapperBase<> is only usable when T has : new()
I had the same issue. I should have read the message before Googling it. I needed to add a parameterless constructor ... :-)
public MyClass() {
//stuff
}

Categories