I have the below code in my Application.
public class GeneralInfo
{
private string _id;
private string _name;
public string id
{
set
{
_id = value;
}
get
{
return _id;
}
}
public string name
{
set
{
_name = value;
}
get
{
return _name;
}
}
}
public class SecureInfo
{
private string _password;
public string password
{
set
{
_password = value;
}
get
{
return _password;
}
}
}
public class User
{
}
I need to apply multiple inheritance in the above code ie. the classes GeneralInfo,SecureInfo properties should be accessible in the user class.
I know using interface Multiple inheritance can be achieved. But i need to define the properties in the base class which is restricted in Interface.
How I can achieve this?
C# does not support multiple inheritance. However you can achieve this via multiple interfaces.
public interface ISecureInfo
{
}
public interface IGeneralInfo
{
}
public class UserClass : ISecureInfo, IGeneralInfo {
}
You probably better off encapsulating the data in the class rather than trying to use something to do multiple inheritance here. See this question for some arguments for this.
You can achieve this through interface based inheritance:
public interface IGeneralInfo
{
String Id { get; set; }
String Name { get; set; }
}
public interface ISecureInfo
String Password { get; set; }
}
public class User : IGeneralInfo, ISecureInfo
{
// Implementation of IGeneralInfo
public String Id { get; set; }
public String Name { get; set; }
// Implementation of ISecureInfo
public String Password { get; set; }
}
Or, going one step further, through composition:
public interface IGeneralInfo
{
String Id { get; set; }
String Name { get; set; }
}
public class GeneralInfo : IGeneralInfo
{
public String Id { get; set; }
public String Name { get; set; }
}
public interface ISecureInfo
String Password { get; set; }
}
public class SecureInfo : IGeneralInfo
{
public String Password { get; set; }
}
public class User : IGeneralInfo, ISecureInfo
{
private GeneralInfo generalInfo = new GeneralInfo();
private SecureInfo secureInfo = new SecureInfo();
public String Id {
get { return generalInfo.Id; }
set { generalInfo.Id = value; }
}
public String Name {
get { return generalInfo.Name; }
set { generalInfo.Name = value; }
}
public String Password {
get { return secureInfo.Password; }
set { secureInfo.Password = value; }
}
}
From your sample description, encapsulation might be what you might want to use:
public class Info{
GeneralInfo general;
SecureInfo secure;
...
}
You cannot do multiple inheritance in C# because it is not supported like C++. In C# you can use interfaces for it and implement method and properties. For sample, you could have a base class
public abstract class Entity
{
public string Name { get; set; }
}
You also could have some interfaces:
public interface IPrint
{
void Print();
}
public interface IGenerate
{
void Generate();
}
And use it like multiples inheritance (but it is not, it is just a single inheritance and interfaces)
public class User : Entity, IPrint, IGenerate
{
public void Print()
{
// some code
// here you could access Name property, because it is on base class Entity
}
public void Generate()
{
// some code
}
}
And you could instance it using the abstractions:
Entity e = new User();
IPrint p = new User();
IGenerate g = new User();
User u = new User();
If you need implementations, you could do a hiearachy inherits, for sample:
User inherit from Person that inherit from Entity.
public class Entity
{
public int Id { get; set; }
public void Method()
{
// some code
}
}
public class Person : Entity
{
public string Name { get; set; }
public void AnotherMethod()
{
// some code
}
}
public class User : Person
{
public string Password { get; set; }
public bool CheckUser(string name, string passworkd)
{
// some code
}
}
I think the best would be to seperate the implementation of the interfaces and the real class you have at the end.
What I mean is something like the Bridge Pattern.
Your class (that will implement several interfaces) will just deleagte the method calls to the real implementation, that you can have in a seperate place and only once.
You could also use an approach like this. You would get to the same point than if you would be using multiple inheritance. That way, you could inherit only Entity if you don't need the SecureInfo stuff (i.e. for books and other stuff). Still, I think composition would do better in this case as others say...
class User : SecuredEntity { }
abstract class SecuredEntity : Entity, ISecureInfo
{
public string Password { get; set; }
}
abstract class Entity : IGeneralInfo
{
public string ID { get; set; }
public string Name { get; set; }
}
interface IGeneralInfo
{
string ID { get; set; }
string Name { get; set; }
}
interface ISecureInfo
{
string Password { get; set; }
}
Related
I've created three interfaces - IUser, ICostCenter, IDepartment. IUser and IDepartment are properties of ICostCenter.
public interface ICostCenter
{
IDepartment Department { get; set; }
User.IUser CostCenterHead { get; set; }
}
The class implementing ICostCenter will be used in the DbContext for my db.
public class tblCostCenter : WorkingInterface.Interface.Organization.ICostCenter
{
public tblCostCenter()
{
this.ID = Guid.NewGuid().ToString();
}
public string ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
private WorkingInterface.Interface.User.IUser CostCenterHead { get; set; }
public string UserID { get; set; }
[ForeignKey("UserID")]
public Model.tblUser UserObject
{
get { return (Model.tblUser)this.CostCenterHead; }
set { this.CostCenterHead = value; }
}
private WorkingInterface.Interface.Organization.IDepartment Department { get; set; }
public string DepartmenID { get; set; }
[ForeignKey("DepartmenID")]
public Model.tblDepartment DepartmentObject
{
get { return (Model.tblDepartment)this.Department; }
set { this.Department = (Model.tblDepartment)value; }
}
}
I'm getting an error because I made the IUser and IDepartment properties private. How can I properly implement the interface? I want these properties to be hidden.
The interface is declared explicitly as public, that means that all the members declared in that interface MUST be public
So you need to declare both of these properties as public:
public WorkingInterface.Interface.User.IUser CostCenterHead { get; set; }
public WorkingInterface.Interface.Organization.IDepartment Department { get; set; }
NOTE: these have been declared as implicit implementations, so they are available to all contexts. If you want to hide them from general use, you can use explicit implementation.
Because you tried to use private accessibility, I assume you generally want to hide these properties from view, you can do this and still honor the interface contract by using explicit implementation syntax:
WorkingInterface.Interface.User.IUser ICostCenter.CostCenterHead { get; set; }
WorkingInterface.Interface.Organization.IDepartment ICostCenter.Department { get; set; }
They are still public but can only be accessed by first casting the object to the specific interface type explicitly.
tblCostCenter obj = new tblCostCenter();
...
// this wont work:
Console.WriteLine(obj.CostCenterHead);
// instead you will have to cast the object first
Console.WriteLine((obj as ICostCenter)).CostCenterHead);
// or if the local variable was an ICostCenter
ICostCenter costObj = obj;
Console.WriteLine(costObj.CostCenterHead);
...
// Pattern matching can also be helpful in these scenarios
if (obj is ICostCenter cc)
Console.WriteLine(cc.CostCenterHead);
If you want to use explicit declaration in your class you could try this:
WorkingInterface.Interface.User.IUser ICostCenter.CostCenterHead { get; set; }
public string UserID { get; set; }
[ForeignKey("UserID")]
public Model.tblUser UserObject
{
get { return ((ICostCenter)this).CostCenterHead as Model.tblUser; }
set { ((ICostCenter)this).CostCenterHead = value; }
}
WorkingInterface.Interface.Organization.IDepartment ICostCenter.Department { get; set; }
public string DepartmenID { get; set; }
[ForeignKey("DepartmenID")]
public Model.tblDepartment DepartmentObject
{
get { return ((ICostCenter)this).Department as Model.tblDepartment; }
set { ((ICostCenter)this).Department = value; }
}
this only works if:
Model.tblDepartment : IDepartment
Model.tblUser : User.IUser
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
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.
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() };
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; }
}
}
I am invoking a method in my constructor like below.Is this the right way to do to set properties based on some validations.Please suggest.
public class Asset
{
public Asset(string id)
{
SetStorageId(id);
}
public string AssetId { get; set; }
public string UtilId { get; set; }
public string MappingId { get; set; }
public bool IsActive { get; set; }
private void SetStorageId(string id)
{
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
AssetId = id;
}
else
{
UtilId = id;
}
}
}
In my opinion your design should be like below,
You should abstract common items to base class and create specific class inheriting this,
and decide from client(consumer) which instance do you need and construct it
public class AssetBase
{
public string MappingId { get; set; }
public bool IsActive { get; set; }
}
public class Asset : AssetBase
{
public string AssetId { get; set; }
}
public class Util : AssetBase
{
public string UtilId { get; set; }
}
static void Main(string[] args)
{
string id = Console.ReadLine();
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
Asset asset = new Asset();
asset.AssetId = id;
}
else
{
Util util = new Util();
util.UtilId = id;
}
}
simply try this
public class Asset
{
private string id;
public string AssetId { get; set; }
public string UtilId { get; set; }
public string Id
{
set
{
if (Regex.Match(value, "^[A-Z][a-zA-Z]*$").Success)
{
this.id = value;
}
else
{
UtilId = value;
}
}
get
{
return id;
}
}
}
When you create a property in c#, a private variable is created for that property on compile time. When you try to set the Id property in the code above the Id you pass goes into the value keyword and you can perform your validations on the value keyword and set your property accordingly.
No need to complicate your code with set methods, constructors or deriving classes
or you can even use data annotations which is a more elegant way https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx#Properties
using System.ComponentModel.DataAnnotations;
public class Asset
{
[RegularExpression("^[A-Z][a-zA-Z]*$")]
public string Id { get; set; }
}
It's not wrong. It can possibly grow to be a little confusing. Maybe you can make it clearer by moving the bod of SetStorageId to the constructor. Perhaps there is no need to complicate with subclassing, relative to other code within the project.
I am trying to implement a hierarchical inheritance structure in Entity Framework, specifically for settings. For example, lets say we have user preferences:
public class StorePreference: Preference { }
public class UserPreference : Preference { }
public class Preference {
public string BackgroundColor { get; set; }
public ContactMethod ContactMethod { get; set; }
}
public enum ContactMethod {
SMS,
Email
}
I'd like it so that if I lookup the user's preferences. If the user doesn't exist or the property value is null, it looks up the parent (store) default preferences.
Ideally, i'd like it to work similar to abstract inheritance:
public class UserPreference : StorePreference {
private string _backgroundColor;
public string BackgroundColor {
get {
if (this._backgroundColor == null)
return base;
return this._backgroundColor;
}
set { this._backgroundColor = value; }
}
}
If I were to write this as a SQL query, it'd be a CROSS APPLY with a CASE statement:
SELECT
CASE WHEN User.BackgroundColor == null THEN Store.BackgroundColor ELSE User.BackgroundColor END BackgroundColor,
CASE WHEN User.ContactMethod == null THEN Store.ContactMethod ELSE User.ContactMethod END ContactMethod
FROM UserPreference User
CROSS APPLY StorePreference Store
WHERE UserPreference.UserId = #UserId
Is there a way I can achieve loading this in EF?
In your base class add default property values:
public class Preference {
public string BackgroundColor { get; set; } = "Red";
public ContactMethod ContactMethod { get; set; } = ContactMethod.SMS;
}
Something like this to set from database:
public class StorePreference : Preference { }
public class UserPreference : Preference { }
public class Preference {
public Preference() {
BackgroundColor = DefaultPreference.BackgroundColor;
ContactMethod = DefaultPreference.ContactMethod;
}
public string BackgroundColor { get; set; }
public ContactMethod ContactMethod { get; set; }
public DefaultPreference DefaultPreference { get; set; }
}
public class DefaultPreference {
public string BackgroundColor { get; set; }
public ContactMethod ContactMethod { get; set; }
}
As long as the properties are public, entity won't have a problem pulling the data from another table as the default. You would need to create a private field to hold the data if you used a setter:
public class ChildTable : EntityBase {
private string _someCategory;
[Key]
[Column(name: "CHILD_ID")]
public override int Id { get; protected set; }
[Column(name: "SOME_CATEGORY")]
public string SomeCategory {
get { return _someCategory; }
set { _someCategory = value ?? ParentTable.SomeCategory; }
}
[ForeignKey("ParentTable")]
[Column(name: "PARENT_ID")]
public int ParentTableId { get; set; }
public virtual ParentTable ParentTable { get; set; }
}
This is just an alternative to a constructor, if you need more control over the setter logic, otherwise Austin's answer would be simpler to implement
I'm currently on design stage in writing C# .NET Core application. I'm gonna use the generics to inherit some properties among all derived classes. The goal is to archive many 2 many relation of entities able to be tagged. The app concept is funky, because tag will contain related logic as constraint entity. I have problems with the proper where statements in generic class, to be able to use inherited Tags property for all Taggable Entities.
Here is abstraction:
public interface ITaggable
{
long TagId { get; set; }
Tag Tag { get; set; }
}
public interface IEntityTag<T> : ITaggable where T : Entity
{
long EntityId { get; set; }
T Entity { get; set; }
}
public abstract class TaggableEntity<T> : Entity where T : ITaggable
{
public ICollection<T> EntityTags { get; set; }
public List<Tag> Tags { get { return EntityTags.Select(x => x.Tag).ToList(); } }
}
public abstract class ConstraintBase<TSubject, TOwner>
: ConstraintEntity where TOwner : TaggableEntity<IEntityTag<TOwner>>
{
protected ConstraintBase(ConstraintId id, string description)
{
Id = id.Value();
Name = id.ToString();
Description = description;
IsExecutable = false;
}
public IEnumerable<TSubject> Validate(IEnumerable<TSubject> items, TOwner owner)
{
return items.Where(x => Validate(x, owner));
}
public void Execute()
{
if (IsExecutable) { OnExecuting(); }
}
protected abstract bool Validate(TSubject item, TOwner owner);
public abstract void OnExecuting();
}
And here concrete classes.
public class ConstraintEntity : Entity
{
public string Name { get; set; }
public string Description { get; set; }
public bool IsExecutable { get; set; }
public ConstraintId ConstraintId => (ConstraintId)Id;
}
public class EndWorkConstraint : ConstraintBase<Activity, User>
{
public EndWorkConstraint() : base(ConstraintId.EndWorkConstraint, "Check if user is allowed to end work")
{
}
protected override bool Validate(Activity item, User owner)
{
return item.ActivityId != ActivityId.EndWork;
}
public override void OnExecuting()
{
throw new System.NotImplementedException();
}
}
public class User : TaggableEntity<UserTag>
{
public string Login { get; set; }
public string Password { get; set; }
}
The question is: am I able to modify ConstraintBase where statement, to make EndWorkConstraint class do not raising an error, and still have the tags explicit avalible?
This is my first post on the forum, and I m really forced to use Yours wisdom. I'd be glad for any tips. Thanks in advance.