Get property default value on class initialize - c#

Let's say we have some class CarsBase
public class CarsBase
{
public string DisplayName { get; set; }
}
Then we have some other class Toyota
public class Toyota : CarsBase
{
public EngineType EngineType { get; set; }
}
Then we are initializing our class instance by using object initializer like so:
var myVar = new Toyota()
{
// DisplayName = "", ← We could do this by our hands, but can it be done automatically?
EngineType = EngineType.UZ
}
Question: Is there any way to fill CarsBase's DisplayName property automatically on object initialize?
Like, if I had several more car classes (BMW, Suzuki , etc.), each is extending CarsBase and as a result have DisplayName property in each class.

This sounds like something that should be done in a constructor.
public class Toyota : CarsBase
{
public Toyota() : base()
{
base.DisplayName = "Toyota";
}
public EngineType EngineType { get; set; }
}
Another option, however less recommended, instead of getting/setting a DisplayName in the same sense, the base class could be changed to use reflection retrieve the classname and use that as the display name:
public class CarsBase
{
public string DisplayName
{
get
{
return this.GetType().Name;
}
}
}
This method should just return the "Toyota" from the classname, however would prevent usage of spaces or other special characters. Reflected code such as this also has a tendency to be slower.

Create a constructor to pass dispay name (or other parameters as required)-
Toyota(string displayName)
{
DisplayName = displayName;
EngineType = EngineType.UZ;
}
Then you can call like this-
new Toyota("some display name");

Just set the property value in the constructor. Something like this:
internal class Program
{
private static void Main(string[] args)
{
Toyota t = new Toyota() { EngineType = new EngineType() };
Console.WriteLine(t.DisplayName);
Console.ReadLine();
}
}
public class CarsBase
{
public string DisplayName { get; set; }
}
public class Toyota : CarsBase
{
public EngineType EngineType { get; set; }
public Toyota()
{
// set the default Display Name
// that way you don't have to set it everytime
this.DisplayName = "Oh what a feeling!";
}
}
public class EngineType { }

Yes, it can be done during the initialization stage of object where constructor is fired . I have created two classes
* one for holding enum constant value for engine_Types --> EngineType
one for explaining the inheritance,Constructor-Chaining, creating an instance of class which is an object----> CarsBase
[pre]
namespace stacketst
{
public class CarsBase
{
public string DisplayName { get; set; }
public CarsBase()
{
//called when CarBase object is initialized
DisplayName = "Base Car";
}
}
public class Toyota : CarsBase
{
//getters , setters called as properties in C#
public int number_of_wheels { get; set; }
public double fuel_capacity { get; set; }
public string engine_type { get; set; }
public Toyota() //called when an instance of Toyota is created
{
//assinging value to this property calls set
fuel_capacity = 4.2;
number_of_wheels = 4;
engine_type = EngineType.name_engines.UZ.ToString();
}
}
public class TestClass
{
static void Main()
{
//when below line is executed,constructor is fired & the initialization of variable inside constructor takes place
var myVar = new Toyota();
Console.WriteLine(myVar.DisplayName);
}
}
}
namespace stacketst
{
public class EngineType
{
//enums to hold constants, common for any Car Class
public enum name_engines
{
V12, V10, V8, V6, UZ
};
}
}
[/pre]

Related

C# Is there a way to make the properties of an object in a class non-editable outside the class itself?

I am looking for a way to have an object in a class and make it non-editable (the object itself AND its properties) outside the class itself but still visible outside.
internal class Room
{
public string Description { get; set; }
}
internal class RoomController
{
public Room Room { get; private set; }
public RoomController()
{
Room = new Room();
}
//Edit the room inside this class
}
internal class Foo
{
public void SomeMethod()
{
RoomController rc = new RoomController();
rc.Room.Description = "something"; // This should not be allowed
string roomDesc = rc.Room.Description; // This should be fine
}
}
Is something like that possible? I couldn't find anything regarding the issue so I would be grateful if anyone has any ideas.
Thanks in advance!
You could define an interface that only exposes the bits you want public:
internal interface IReadonlyRoom
{
string Description { get; } //note only getter exposed
}
internal class Room : IReadonlyRoom
{
public string Description { get; set; }
}
internal class RoomController
{
private Room _room;
public IReadonlyRoom Room => _room;
public RoomController()
{
_room = new Room();
}
//edit using _room
}

How to access List<Interface> object properties when it's class is inherited from interface?

Ok, so here's the problem. I have an interface IBook, which includes property Name. There is two classes which inherit from the IBook and add their own property Genre. I wanna create a Dictionary or a List and add all kinds of books there and access them by string and their properties so I made it Dictionary. In the example, I can access books["LOTR"].Name but not books["LOTR"].Genre, propably because Name is property of the IBook interface but Genre is property of the class that inherits from the IBook.
Is it possible to make the Dictionary or List work with the interface type and still be able to access all the inheriting class properties as well, or should I use an array or something?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp124
{
interface IBook
{
string Name { get; set; }
}
public class FantasyBook:IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
public class HorrorBook : IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
Dictionary<string, IBook> books = new Dictionary<string,
IBook>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
Console.ReadLine();
}
}
}
An alternative approach is to add another layer of interface with Genre and use pattern matching for accessing the properties:
interface IBook
{
string Name { get; set; }
}
interface IBookWithGenre : IBook
{
string Genre { get; set; }
}
public class FantasyBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class SimpleBook : IBook
{
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
SimpleBook abook = new SimpleBook();
var books = new Dictionary<string, IBook>
{
{ "LOTR", LordOfTheRings },
{ "Frankenstein", Frankenstein },
{ "Simple", abook },
};
books["LOTR"].Name = "Lord Of The Rings";
if (books["LOTR"] is IBookWithGenre withGenre)
{
withGenre.Genre = "Fantasy";
}
Console.ReadLine();
}
}
The comments are pretty much on point - you cannot do that as the compiler will examine available members on the IBook (since you declared it) and will not let you shoot yourself in the foot by trying to access a property that's not defined there. This is static type checking.
But let's for a second imagine you don't care about type safety and performance. It turns out, you have an option then. Well, sort of...as you will still have to give up your specific IBook for dynamic
interface IBook {
string Name { get; set; }
}
public class FantasyBook : IBook
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBook
{
public string Name {get;set;}
public string Genre {get;set;}
}
public class BadaBook : IBook // so I added this new class that does not implement Genre to illustrate a point
{
public string Name { get; set; }
}
static void Main(string[] args)
{
var LordOfTheRings = new FantasyBook();
var Frankenstein = new HorrorBook();
var Badaboom = new BadaBook();
Dictionary<string, dynamic> books = new Dictionary<string, dynamic>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books.Add("Badaboom", Badaboom);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
books["Badaboom"].Name = "We can easily assign Name as it is defined. No problem here";
books["Badaboom"].Genre = "But we will miserably fail here"; // RuntimeBinderException: 'UserQuery.BadaBook' does not contain a definition for 'Genre'
Console.ReadLine();
}
Check out dynamic for further reading. It comes with the risks outlined in my example as well as performance penalties. It's not bad per se, it just needs to be taken in moderation.

AutoMapper isn't recognizing profile-specific prefixes

I'm trying to use AutoMapper to take data from a class that has prefixes before property names and map it to a second class that doesn't have those prefixes. However, I don't necessarily want it to always strip out that prefix: I just want it to do it for this particular mapping.
My source class looks like this:
public class AdvancedSearchFilterDataModel
{
// ....
public string ServiceMeterNumber { get; set; }
// ....
}
My destination class looks like this:
[DataContract]
public class ServicesAdvancedSearchFilterData : AdvancedSearchFilterData
{
// ....
[DataMember]
public string MeterNumber { get; set; }
// ....
}
When I try to map values like this, it works:
Mapper.Configuration.RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>();
ServicesAdvancedSearchFilterData servciesFilterData =
Mapper.Map<ServicesAdvancedSearchFilterData>(model);
But I only want "Service" to be recognized as a prefix for certain mappings, since it's also used as a normal part of property names in other mappings. I tried to handle this with a profile, but this didn't work -- no data was mapped:
Mapper.CreateProfile("ServicePrefix").RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>()
.WithProfile("ServicePrefix");
ServicesAdvancedSearchFilterData servciesFilterData =
Mapper.Map<ServicesAdvancedSearchFilterData>(model);
How can I make it recognize the prefix only when I want it to, either using profiles or some other technique? (I also have other prefixes that I'm going to need it to recognize for other mappings in the same way.)
I achieved this functionality by creating following structure:
I have Person model for my view which is flattened from PersonCombined
public class PersonCombined
{
public Person Person { get; set; }
public Address DefaultAddress { get; set; }
public Contact EmailContact { get; set; }
public Contact PhoneContact { get; set; }
public Contact WebsiteContact { get; set; }
}
public class Person : IWebServiceModel
{
public int ID { get; set; }
public string PersonFirstName { get; set; }
public string PersonSurname { get; set; }
public string PersonDescription { get; set; }
public Nullable<bool> PersonIsActive { get; set; }
}
Then I have separate class for this mapping only that looks like this:
public class PersonCustomMapping : ICustomMapping
{
const string separator = " ";
private static IMappingEngine _MappingEngine;
public IMappingEngine MappingEngine
{
get
{
if (_MappingEngine == null)
{
var configuration = new ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);
configuration.RecognizePrefixes("Person");
configuration.RecognizeDestinationPrefixes("Person");
configuration.CreateMap<Person, MCIACRM.Model.Combine.PersonCombined>();
configuration.CreateMap<MCIACRM.Model.Combine.PersonCombined, Person>();
_MappingEngine = new MappingEngine(configuration);
}
return _MappingEngine;
}
}
}
In my generic view I have mappingEngine property like this:
private IMappingEngine mappingEngine
{
get
{
if (_mappingEngine == null)
{
_mappingEngine = AutoMapper.Mapper.Engine;
}
return _mappingEngine;
}
}
Finally in my generic view constructor i have:
public GenericEntityController(IGenericLogic<S> logic, ICustomMapping customMapping)
: base()
{
this._mappingEngine = customMapping.MappingEngine;
this.logic = logic;
}
And that's how I do mapping:
result = items.Project(mappingEngine).To<R>();
or
logic.Update(mappingEngine.Map<S>(wsItem));
Because I use 1 entity per view I can define custom mapping configuration per entity.
Hope this helps

Update the Base Class attributes when instantiate Child class C#

I want the following, is it possible in C#
public class BaseClass
{
public string Name {get;set;}
public DateTime Login {get;set;}
}
public class ChildA : BaseClass
{
public string SchoolName{get; set;}
public string ClassName{get; set;}
}
public class childB : BaseClass
{
public string StreetAdrees{get; set;}
}
Now I want that if I create an instance of any child class Name="John" and Login "2013-12-12" or from database already set its irritating to set these attribute for every class
just like that
ChildA obj=new ChildA();
obj.Name and obj.Login already have Data
Specify constructor in base class, then create constructors in child classes which inherit from base classes constuctor like below
public class ChildA : BaseClass
{
public ChildA():base(){}
public string SchoolName{get; set;}
public string ClassName{get; set;}
}
public class BaseClass
{
public BaseClass()
{
//set Data
.....
}
....
}
read more about base keyword
In the example below, children would actually point to the same instance of base
The example uses cache, but it could be anything else (session, application state, etc).
public class BaseClass
{
private string _name;
private DateTime _login;
public string Name
{
get
{
return Instance._name;
}
set
{
_name = value;
}
}
public DateTime Login
{
get
{
return Instance._login;
}
set
{
_login = value;
}
}
public static BaseClass Instance
{
get
{
// check if null, return a new instance if null etc...
return HttpContext.Current.Cache["BaseClassInstance"] as BaseClass;
}
set
{
HttpContext.Current.Cache.Insert("BaseClassInstance", value);
}
}
}
public class ChildA : BaseClass
{
public string SchoolName { get; set; }
public string ClassName { get; set; }
}
public class childB : BaseClass
{
public string StreetAdrees { get; set; }
}
testing it:
BaseClass.Instance = new BaseClass() { Login = DateTime.Now, Name = "Test" };
ChildA ch = new ChildA();
ChildA ch2 = new ChildA();
childB chb = new childB();
Response.Write(ch.Login.Millisecond);
Response.Write("<BR/>");
Response.Write(chb.Login.Millisecond);
Result:
906
906

DisplayAttribute - How can I set a default Resource?

I have a poco class Product
public class Product
{
public int Id {get;set;}
[RequiredEx]
public string ProductName {get;set;}
}
the RequiredEx attribute ist just a little wrapper around RequiredAttribute (System.ComponentMode.DataAnnotations` so I don't have to specify the Resource type / name every time.
public class RequiredExAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute
{
public RequiredExAttribute()
{
this.ErrorMessageResourceType = typeof(ModelResources);
this.ErrorMessageResourceName = "ErrorMessage.Required";
}
}
Now I want to decorate my property with the Display attribute
[Display(ResourceType=typeof(ModelResources), Name="Product.ProductName")]
public string ProductName { get; set; }
In this case I can't just inherit from DisplayAttribute because it is sealed. Is there any chance for me not to have to type ResourceType=typeof(ModelResources) everytime I use this Attribute?
Since the attribute is sealed, and isn't part of a more complex OO model (the base class is just Attribute, and there are no interfaces implemented), I can't see that you have any options available to you here. Basically, I expect the answer is simply: "you will heed to specify the ResourceType every time".
If you're only using the Name property of the DisplayAttribute you can achieve this by inheriting from the (older) DisplayNameAttribute, which is not sealed:
using System.Resources;
namespace System.ComponentModel
{
public class LocalisedDisplayNameAttribute
: DisplayNameAttribute
{
readonly ResourceManager m_resourceManager;
readonly string m_resourceName;
public LocalisedDisplayNameAttribute(ResourceManager resourceManager,
string resourceName)
: base()
{
m_resourceManager = resourceManager;
m_resourceName = resourceName;
}
public override string DisplayName
{
get { return m_resourceManager.GetString(m_resourceName); }
}
}
}
You can then set up display attributes for your common string resources:
public class DisplayBizAttribute
: LocalisedDisplayNameAttribute
{
public DisplayBizAttribute(string resourceName)
: base(StringsBiz.ResourceManager, resourceName)
{
}
}
public class DisplayWebAttribute
: LocalisedDisplayNameAttribute
{
public DisplayBizAttribute(string resourceName)
: base(StringsWeb.ResourceManager, resourceName)
{
}
}
And then you can localise your property display names very easily, with string literals or constants:
[DisplayBiz("ProductName")]
public string ProductName { get; set; }
[DisplayBiz(StringNames.PHONE_NUMBER)]
public string ProductName { get; set; }
[DisplayWeb("EmailAddress")]
public string EmailAddress { get; set; }
Update
This can be improved by declaring an enum in each attribute class, and changing the constructor, or adding a new one:
public class DisplayBizAttribute
: LocalisedDisplayNameAttribute
{
public enum Name
{
PhoneNumber,
ProductName,
}
public DisplayBizAttribute(Name resourceName)
: base(StringsBiz.ResourceManager, resourceName.ToString())
{
}
}
Now you don't have to use hard-coded strings.
[DisplayBiz(DisplayBiz.Name.ProductName)]
public string ProductName { get; set; }
This is something you do a lot, so I like to add a using to shorten the enum:
using Biz = System.ComponentModel.DisplayBiz.Name;
...
[DisplayBiz(Biz.PhoneNumber)]
public string PhoneNumber { get; set; }

Categories

Resources