Tejas
Tejas

Reputation: 461

Generic Attributes in MVC models

I created the GenericAttribute.cs file in my Models

public class GenericAttributes<T>
{
    public T Id { get; set; }
    public bool IsActive { get; set; }
    public DateTime CreatedDate { get; set; }
}

Now I want to add 'int id' field in my User Model

public class User
{
    //here I want to add 'Id' field
    public string UserId { get; set; }
    public string password { get; set; }
    public string UserType { get; set; }
    public int EmployeeId { get; set; }

    public virtual Employee employee { get; set; }
}

How should I do this? Please help

Upvotes: 0

Views: 232

Answers (3)

Ryan Pierce Williams
Ryan Pierce Williams

Reputation: 1004

You are getting some conflicting answers due to your naming convention. Any class of the form xxxAttribute is expected to be a subclass of the Attribute class. Attributes are metadata that you can attach to classes, fields, etc. Using reflection you can read these attributes, which is a powerful way to inform various APIs about how to interact with your custom classes - without inheritance or an interface.

If this sort of metadata is your intent, then Barr J's answer is correct. However, if your intent is for the GenericAttributes class to serve as a base class that you can inherit these properties from, then Tom Johnson is correct (although he did change GenericAttributes into an interface instead of a base class, but same result if all you have are properties like this). The latter is most likely what you are looking for.

I would suggest renaming GenericAttributes to something more descriptive, like BaseRecord or IRecord (as an interface), since User looks like data coming from or going to a database.

It would also be handy to have a non-generic version of the class/interface so that you can non-generically reference such records.

public class BaseRecord {
    public Type IdType { get; }

    private Object _id = null;
    public Object Id { 
        get {
            return _id;
        }
        set {
            if(value != null) {
                if(!IdType.IsAssignableFrom(value.GetType()))
                    throw new Exception("IdType mismatch");
            }
            _id = value;
        }
    }

    public bool IsActive { get; set; }
    public DateTime CreatedTime { get; set; }

    public BaseRecord(Type idType)
    {
        if(idType == null) throw new ArgumentNullException("idType");
        this.IdType = idType;
    }
}

namespace Generic {
    public class BaseRecord<T> : BaseRecord
    {
        new public T Id {
            get { return (T)base.Id; }
            set { base.Id = value; }
        }            

        public BaseRecord() : base(typeof(T))            
        {
        }
    }
}

public class User : Generic.BaseRecord<int>
{}

public class OtherRecord : Generic.BaseRecord<string>
{}

// This inheritence scheme gives you the flexibility to non-generically reference record objects 
// which can't be done if you only have generic base classes
BaseRecord r = new User();
r = new OtherRecord();
BaseRecord records[] = { new User(), new OtherRecord() };

Upvotes: 1

Ajay
Ajay

Reputation: 653

To access the id for GenericAttributes class, you'll have to cast User object as base class type.

namespace SampleApp
{
    class SampleProgram
    {
        static void Main(string[] args)
        {
            User User = new User() { Id = 1 };
            var genericAttribute = (User as GenericAttributes<int>);
            genericAttribute.Id = 2;
            var genericAttributeId = genericAttribute.Id;
            var classId = User.Id;
        }
    }
    public class GenericAttributes<T>
    {
        public T Id { get; set; }
    }
    public class User : GenericAttributes<int>
    {
        public new int Id { get; set; }
    }
}

Upvotes: 0

Tom Johnson
Tom Johnson

Reputation: 689

You can make GenericAttributes an interface so you can implement it where ever.

Such as;

public interface IGenericAttributes<T>
{
 //properties
}

And use in your class declaration;

public class User : IGenericAttributes<int>
{
//properties
}

This will force your concrete type User to implement the properties of the interface.

Upvotes: 2

Related Questions