I need to build an attribute that will override the getter and the setter of an property. To be more clear, here is how it works today and how it should work using the attribute (the result should be the same).
Old version:
public class A
{
private Handle _handle;
public String StringProp
{
get {
return _handle.GetProperty(PropId.StringProp);
}
set {
_handle.SetProperty(PropId.StringProp, value);
}
}
public int IntProp
{
get {
return _handle.GetProperty(PropId.IntProp);
}
set {
_handle.SetProperty(PropId.IntProp, value);
}
}
}
New version:
public class A
{
private Handle _handle;
[HandleProperty(PropId.StringProp)]
public String StringProp { get; set; }
[HandleProperty(PropId.IntProp)]
public int IntProp { get; set; }
}
The attribute HandleProperty should known to link the getter and setter to _handle.GetProperty and _handle.SetProperty.
I created two enums and some of the fields in one enum were mapped to another enums fields using attributes. I think you can do something like this...
[AttributeUsage(AttributeTargets.Field)]
public sealed class MapsToAttribute : Attribute
{
private string Text;
public string MapsToText
{
get
{
return Text;
}
}
public MapsToAttribute(string mapsToText)
{
Text = mapsToText;
}
public override string ToString()
{
return Text;
}
}
Related
I want a class/record with protected set and public init access restriction?
To my knowledge this even cannot be done by explicitly implementing a "Set" interface like this:
public interface ISetData<T>
{
T Value { get; set; }
}
public class Data : ISetData<bool>
{
bool ISetData<bool>.Value { get => Value; set => Value = value; } // Error The property Value has no setter
public bool Value { get; init; }
}
Downside is, set functionality is public when using the interface. Not good. (for internal components the interface can be made internal, but that's mostly no option)
Given that only derivations of Data should be able to set data after initialization, the only solution I see is to use an backing field for the property, which is annoying.
Which looks like:
public interface ISetData<T>
{
T Value { get; set; }
}
public class Data : ISetData<bool>
{
bool ISetData<bool>.Value { get => Value; set => _value = value; } // Fine
private bool _value;
public bool Value
{
get { return _value; }
init { }
}
}
That seems odd to me. Would it not be better CLR/c# allows to use access modifiers independently of set/init this like:
public class Data
{
public bool Value { get; init; protected set; }
}
I know this would better be addressed by a feature request, but this is not what this post is about.
So what solutions are available for the scenario "public init, but protected set"?
A simple answer is none.
In C# 9.0, you could have either init or protected set, not both.
You could have a separate property that is protected set and then the public property can be based on your protected property. Example below.
using System;
public class Program
{
public static void Main()
{
var example = new Example{Test = "hello world"};
example.PrintProtectedTest();
Console.WriteLine(example.Test);
example.SetProtectedTest("goodbye world");
Console.WriteLine(example.Test);
}
}
class Example
{
public Example()
{
}
protected string ProtectedTest { get; set; }
public string Test
{
get => ProtectedTest;
init => ProtectedTest = value;
}
public void SetProtectedTest(string test)
{
ProtectedTest = test;
}
public void PrintProtectedTest()
{
Console.WriteLine(ProtectedTest);
}
}
You can run the example here https://dotnetfiddle.net/odGwDj
I"m trying to put together an abstract class that various models in my MVVM will derive from. Part of this is for abstracting IEditableObject/IChangeTracking details.
For my IEditableObject, I want to store a shallow copy of "core data" (a struct that defines data that will be serialized, typically for database storage) so that it can be cancelled or committed. What I don't want to do is type this out for each new Model that I come up with.
I've defined a [DataCoreItem] custom attribute that I thought to use on the derived class's applicable properties. For some unrelated reasons, the abstract class takes a generic DataCoreType and IDType:
public abstract class ModelObject<T, DataCoreType, IDType> : INotifyPropertyChanged, IEditableObject
{
public abstract DataCoreType Load(IDType id);
public abstract bool Save(DataCoreType dataCore);
public abstract bool Delete(IDType id);
// etc...
Here's an example for my CompanyModel
the data core:
public struct CompanyDataCore
{
public int? ID;
public string Code;
public string Name;
public string PrimaryWebsite;
public string PrimaryPhone;
public string PrimaryEmail;
}
the derived class:
public class CompanyModel : ModelObject<CompanyModel, CompanyDataCore, int> {
CompanyDataCore dataCore;
[DataCoreMember]
public int? ID { get { return dataCore.ID; } set { SetProperty(ref dataCore.ID, value); } }
[DataCoreMember]
public string Name { get { return dataCore.Name; } set {SetProperty(ref dataCore.Name, value); } }
[DataCoreMember]
public string Code { get { return dataCore.Code; } set { SetProperty(ref dataCore.Code, value); } }
[DataCoreMember]
public string PrimaryPhone { get { return dataCore.PrimaryPhone; } set {SetProperty(ref dataCore.PrimaryPhone, value); } }
[DataCoreMember]
public string PrimaryEmail { get { return dataCore.PrimaryEmail; } set { SetProperty(ref dataCore.PrimaryEmail, value); } }
[DataCoreMember]
public string PrimaryWebsite { get { return dataCore.PrimaryWebsite; } set { SetProperty(ref dataCore.PrimaryWebsite, value); } }
Ok, finally... what I'd like for my abstract class is to use the BeginEdit(), EndEdit() and CancelEdit() methods to handle storage of a backup copy of the data core automatically. Here's how I envision it:
[DataCoreMember(MemberName="ID")]
public int? ID { get { return dataCore.ID; } set { SetProperty(ref dataCore.ID, value); } }
// etc etc
and in my abstract class:
public virtual void BeginEdit() {
Type t = typeof(T);
var props = t.GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(DataCoreMemberAttribute)));
// WHAT TO DO HERE??? everything else looks good up to here
foreach (object o in props) {
this.dataCoreBackup.???? = o.value;
}
IsEditing = true;
}
How to map the property to which the DataCoreMember is applied to the property of the struct as specified?
I'm inexperienced with reflection (and working generic types as well for that matter), but I gather that this can be done. I've found examples (as of yet untried) for how to get a list of those properties with the attribute applied to them, but I'm unsure how to ultimately reference the DataCore's property based on that. Can anyone show me how? Much appreciated.
Turns out it was a fairly easy task with Reflection. Explanation below (with much of the non-pertinent code stripped out)
This holds the data backup so CancelEdit is supported:
public struct CompanyDataCore
{
public int? ID;
public string Code;
public string Name;
public string PrimaryWebsite;
public string PrimaryPhone;
public string PrimaryEmail;
public string RootPath;
}
Here's the attribute class to denote which fields get backed up:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class DataCoreMemberAttribute : Attribute
{
public string MemberName { get; set; }
}
This is the derived class:
public class CompanyModel : ModelObject<CompanyModel, CompanyDataCore, int>
{
[Identifier]
[DataCoreMember(MemberName="ID")]
public int? ID { get { return dataCore.ID; } set { SetProperty(ref dataCore.ID, value); } }
[DataCoreMember(MemberName="Name")]
public string Name { get { return dataCore.Name; } set {SetProperty(ref dataCore.Name, value); } }
[DataCoreMember(MemberName="Code")]
public string Code { get { return dataCore.Code; } set { SetProperty(ref dataCore.Code, value); } }
[DataCoreMember(MemberName="PrimaryPhone")]
public string PrimaryPhone { get { return dataCore.PrimaryPhone; } set {SetProperty(ref dataCore.PrimaryPhone, value); } }
[DataCoreMember(MemberName="PrimaryEmail")]
public string PrimaryEmail { get { return dataCore.PrimaryEmail; } set { SetProperty(ref dataCore.PrimaryEmail, value); } }
[DataCoreMember(MemberName="PrimaryWebsite")]
public string PrimaryWebsite { get { return dataCore.PrimaryWebsite; } set { SetProperty(ref dataCore.PrimaryWebsite, value); } }
}
And here's the abstract class:
public abstract class ModelObject<T, DataCoreType, IDType> : INotifyPropertyChanged, IEditableObject
{
protected DataCoreType dataCoreBackup;
public virtual void BeginEdit() {
Type t = typeof(T);
// get a the properties with the attribute
var props = t.GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(DataCoreMemberAttribute)));
// backup needs to be boxed because it's a struct
object boxedBackup = this.dataCoreBackup;
foreach (var prop in props) {
foreach (CustomAttributeData attribData in prop.GetCustomAttributesData()) {
if (attribData.Constructor.DeclaringType == typeof(DataCoreMemberAttribute)) {
object origValue = prop.GetValue(this);
FieldInfo field = boxedBackup.GetType().GetField(attribData.NamedArguments[0].TypedValue.Value.ToString());
field.SetValue(boxedBackup, origValue);
}
}
}
this.dataCoreBackup = (DataCoreType)boxedBackup;
IsEditing = true;
}
... and now I can get INotifiyPropertyChanged and IEditbaleObject handled in an abstract class so I don't have to write a bunch of plumbing in each specific model that I'm going to use.
Hopefully someone else can find this useful.
I have an object model that has a property like this:
public class SomeModel
{
public string SomeString { get; set; }
public void DoSomeWork()
{
....
}
}
I want the DoSomeWork function to execute automatically after the SomeString property changes. I tried this but it's not working:
public string SomeString { get; set { DoSomeWork(); } }
What's the correct syntax?
Use a private field instead, like this ...
public class SomeModel
{
private string someString = "";
public string SomeString {
get { return this.someString; }
set {
this.someString = value;
this.DoSomeWork();
}
}
public void DoSomeWork()
{
....
}
}
You can't do this with automatic properties - you'll have to create a "manual" property backed by a field.
private string _someString;
public string SomeString
{
get { return _someString; }
set
{
_someString = value;
DoSomeWork();
}
}
If you really can't deal with this boilerplate (say you'd have to do this hundreds of times), consider using an AOP framework like PostSharp to implement this on your behalf - you'd just need to declare an automatic property and an attribute to get the binary rewriter to implement the desired scheme.
This will work...
private string _someString;
public string SomeString { get { return _someString; } set { _someString = value; DoSomeWork(); } }
private string _someString;
public string SomeString
{
get
{
return _someString;
}
set
{
DoSomeWork();
_someString = value;
}
}
C# team has introduced the auto-implement properties in C# 3.0. with the logic of minimizing the model making which is backed by an anonymous field created by compiler. this one is used when you don't need to implement any additional logic on a property of an object class. so it just followed as.
public string Name{ get; set;}// auto-implemented property. no additional logic.
if we want to add some logic as you want to add one function. we must be writing a manual property backed by a private field as like below.
private string _Name;
public string Name
{
get {return _Name;}
set {
_Name=value;
DoSomething(); //Additional logic implemented.
}
}
I'm hoping someone can assist me with understanding if/how something like this is possible.
In this scenario, imagine you are trying to model a grid like a spreadsheet or in a DB, but where the data in each column can only be of one data type.
Example: Column 1 can only contain integers.
I created a generic class to model the column structure that looks like this:
public class CollectionColumn<T>
{
private string _name;
private string _displayName;
private List<T> _dataItems = new List<T>();
public string Name {
get { return _name; }
set { _name = value; }
}
public string DisplayName {
get { return _displayName; }
set { _displayName = value; }
}
public List<T> Items {
get { return _dataItems; }
set { _dataItems = value; }
}
}
Now what I want to do is have a container for the various columns (there could be CollectionColumn, CollectionColumn, etc.) with it's own properties, but I'm not sure how to do that where I can still access the columns and the data within them when I don't know their types.
This is a .NET 2.0 project so something like dynamic would not work, maybe a list of object? I am also not sure if there is a way to do this with interfaces.
public class ColumnCollection
{
public int Id { get; set; }
public string ContainerName { get; set; }
private List<CollectionColumn<T>> _columns;
public List<CollectionColumn<T>> Columns {
get { return _columns; }
set { _columns = value; }
}
}
What I want to be able to do is add various CollectionColumn's to the Columns collection of a ColumnCollection so I can have columns containing various types of data.
Any help would be very much appreciated.
This is a fairly common problem. What you need to do is either declare a non-generic base class that your generic class inherits from or a non-generic interface that your generic class implements. You can then make your collection of that type.
For example,
public abstract class CollectionColumnBase
{
private string _name;
private string _displayName;
public string Name {
get { return _name; }
set { _name = value; }
}
public string DisplayName {
get { return _displayName; }
set { _displayName = value; }
}
public abstract object GetItemAt(int index);
}
public class CollectionColumn<T> : CollectionColumnBase
{
private List<T> data = new List<T>();
public overrides object GetItemAt(int index)
{
return data[index];
}
public List<T> Items
{
get { return data; }
set { data = value; }
}
}
public class ColumnCollection
{
public int Id { get; set; }
public string ContainerName { get; set; }
private List<CollectionColumnBase> _columns;
public List<CollectionColumnBase> Columns {
get { return _columns; }
set { _columns = value; }
}
}
I'm trying to create a set of classes where a common ancestor is responsible for all the logic involved in setting various properties, and the descendants just change the access of properties depending on whether they are required in the particular descendant.
When I try to do it as shown below I get a compiler error: "cannot change access modifiers when overriding 'protected' inherited member"
Is there a way to achieve what I'm trying to do? Thanks
public class Parent
{
private int _propertyOne;
private int _propertyTwo;
protected virtual int PropertyOne
{
get { return _propertyOne; }
set { _propertyOne = value; }
}
protected virtual int PropertyTwo
{
get { return _propertyTwo; }
set { _propertyTwo = value; }
}
}
public class ChildOne : Parent
{
public override int PropertyOne // Compiler Error CS0507
{
get { return base.PropertyOne; }
set { base.PropertyOne = value; }
}
// PropertyTwo is not available to users of ChildOne
}
public class ChildTwo : Parent
{
// PropertyOne is not available to users of ChildTwo
public override int PropertyTwo // Compiler Error CS0507
{
get { return base.PropertyTwo; }
set { base.PropertyTwo = value; }
}
}
You can do this by using "new" instead of "override" to hide the parent's protected property as follows:
public class ChildOne : Parent
{
public new int PropertyOne // No Compiler Error
{
get { return base.PropertyOne; }
set { base.PropertyOne = value; }
}
// PropertyTwo is not available to users of ChildOne
}
public class ChildTwo : Parent
{
// PropertyOne is not available to users of ChildTwo
public new int PropertyTwo
{
get { return base.PropertyTwo; }
set { base.PropertyTwo = value; }
}
}
You can't change the access, but you can re-declare the member with greater access:
public new int PropertyOne
{
get { return base.PropertyOne; }
set { base.PropertyOne = value; }
}
The problem is that this is a different PropertyOne, and inheritance / virtual might not work as expected. In the above case (where we just call base.*, and the new method isn't virtual) that is probably fine. If you need real polymorphism above this, then you can't do it (AFAIK) without introducing an intermediate class (since you can't new and override the same member in the same type):
public abstract class ChildOneAnnoying : Parent {
protected virtual int PropertyOneImpl {
get { return base.PropertyOne; }
set { base.PropertyOne = value; }
}
protected override int PropertyOne {
get { return PropertyOneImpl; }
set { PropertyOneImpl = value; }
}
}
public class ChildOne : ChildOneAnnoying {
public new int PropertyOne {
get { return PropertyOneImpl; }
set { PropertyOneImpl = value; }
}
}
The important point in the above is that there is still a single virtual member to override: PropertyOneImpl.
NO. Still you can Hide the inherited property with Your's
public class ChildTwo: Praent {
public new int PropertyTwo {
// do whatever you want
}
}
ps: this is no longer virtual/override relationship (i.e. no polymorphic calls)