简体   繁体   中英

Assistance needed with generic types - type cannot be used as a type parameter

I have come across a slight issue with my class design and I am having trouble with dealing with it. Having searched the web to no avail I am hoping someone here would be kind enough to point me in the right direction. I have posted the entire code so in theory, should be able to do a simple copy and paste in VS and visualise the error.

Thanks in advance, Onam.

Full error: The type 'Complainant' cannot be used as type parameter 'T' in the generic type or method 'Person'. There is no implicit reference conversion from 'Complainant' to 'ObjectFactory'.

#region : Complainant :
public class Complainant : Person<Complainant>
{
    #region Properties...

    #region ComplainantId
    public Int64 ComplainantId { get; private set; }
    #endregion

    #region IsApproachable
    public bool IsApproachable { get; set; }
    #endregion

    #endregion

    #region Constructors...
    public Complainant()
    {
    }
    #endregion

    #region Methods...

    #region Load
    public void Load(Int64 objectId)
    {
        base.Hydrate(objectId);
    }
    #endregion

    #endregion
}
#endregion

#region : Person :
public class Person<T> : ObjectFactory<T>
{
    #region Properties...

    #region PersonId
    public Int64 PersonId { get; protected set; }
    #endregion

    #region DOB
    public DateTime DOB { get; set; }
    #endregion

    #region Email
    public string Email { get; set; }
    #endregion

    #region Forename
    public string Forename { get; set; }
    #endregion

    #region Fullname
    public string Fullname { get { return Forename + " " + Surname; } }
    #endregion

    #region HomeTel
    public string HomeTel { get; set; }
    #endregion

    #region Initials
    public string Initials { get; set; }
    #endregion

    #region Mobile
    public string Mobile { get; set; }
    #endregion

    #region Surname
    public string Surname { get; set; }
    #endregion

    #region WorkTel
    public string WorkTel { get; set; }
    #endregion

    #endregion

    #region Constructor
    public Person()
    {
    }
    #endregion
}
#endregion

#region : Property :
public class Property
{
    #region Properties...

    #region Inherits
    [XmlAttribute("Inherits")]
    public string Inherits { get; set; }
    #endregion

    #region IsPrimaryKey
    [XmlAttribute("IsPrimaryKey")]
    public bool IsPrimaryKey { get; set; }
    #endregion

    #region Name
    [XmlAttribute("Name")]
    public string Name { get; set; }
    #endregion

    #endregion

    #region Constructors...

    public Property(string name, bool isPrimaryKey)
    {
        this.Name = name;
        this.IsPrimaryKey = isPrimaryKey;
    }

    public Property()
    {
    }

    #endregion

    #region Methods


    #endregion
}
#endregion

#region : ObjectFactory :
public class ObjectFactory<T> where T : new()
{
    #region Members...
    static Expression<Func<T>> __x = () => new T();
    static Func<T> __function = __x.Compile();
    static Dictionary<Type, List<Property>> __cache = new Dictionary<Type, List<Property>>();
    #endregion

    #region Constructors
    public ObjectFactory()
    {
        Type _type = typeof(T);

        if (!__cache.ContainsKey(_type))
        {
            __cache.Add(_type, Deserialize(_type.Name));
        }
    }
    #endregion

    #region Methods

    #region Build
    public static T Build()
    {
        return __function();
    }
    #endregion

    #region Deserialize
    private List<Property> Deserialize(string objectName)
    {
        XmlSerializer _serializer = new XmlSerializer(typeof(List<Property>));
        using (Stream _stream = File.OpenRead(String.Format(@"C:\_XMLFiles\{0}.xml", objectName)))
        {
            return (List<Property>)_serializer.Deserialize(_stream);
        }
    }
    #endregion

    #region Hydrate
    protected void Hydrate(Int64 objectId)
    {
        List<Property> _properties = new List<Property>();

        if (__cache.TryGetValue(typeof(T), out _properties))
        {
            object[] o = typeof(T).GetProperties();
            foreach (PropertyInfo pi in typeof(T).GetProperties())
            {
                string s = pi.Name;
                //if (pi.Name == name)
                //{
                    //pi.SetValue(this, value, null);
                //}
            }
        }
    }
    #endregion

    #endregion
}
#endregion

I'm not 100% sure if this is the reason - but you should maintain the generic parameter constraints on the Person<T> class. So add the where T : new() to the Person<T> class.

EDIT

After compiling your code, I get the error:

Error 1 '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 'Reflection.ObjectFactory' SomeClass.cs 67 18 Reflection

This error is solved by the addition of the where clause I mentioned above. After that point, I get no compilation errors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM