I have the following class that lets certain objects subscribe to a change event. The problem is that I also have classes B, and C that need this functionality that allow objects to subscribe to the same kind of thing. We certainly don't want to copy and paste this behaviour.
We've considered inheriting from a common base class, but all our classes including A, B, and C already inherit from a common BaseClass. And we don't want to add this behaviour to BaseClass because our other classes E,F,G that inherit from BaseClass don't need this behaviour.
Is there a better solution?
public class A : BaseClass
{
/*other properties and code */
public event EventHandler OnChange;
private bool _hasChanged;
public bool HasChanged
{
get { return _hasChanged; }
set
{
_hasChanged = value;
//only need to notify when we've changed.
if (value)
{
if (OnChange != null)
OnChange(this, EventArgs.Empty);
}
}
}
}
Consider an aspect-oriented programming approach, like the one used in this PostSharp example. It would allow you to inject that kind of boilerplate code using attributes.
If you created the appropriate aspect, you could then have code like:
public class A : BaseClass
{
public event EventHandler OnChanged;
[ChangedNotify("OnChanged")]
public bool HasChanged { get; set; }
}
or, if the idea is to have a single OnChange event for multiple properties, you could just hard-code that into the aspect, reducing your code to
public class A : BaseClass
{
[NotifyOnChanged]
public bool HasChanged { get; set; }
}
What if we don't use inheritance for a moment?
1- Suppose , Instead of inheriting from a common base class, Compose your client class which requires event mechanism with a object which implement event mechanism.
Suppose our class is
public class EventNotifier
{
public event EventHandler OnChange;
private bool _hasChanged;
public bool HasChanged
{
get { return _hasChanged; }
set
{
_hasChanged = value;
//only need to notify when we've changed.
if (value)
{
if (OnChange != null)
OnChange(this, EventArgs.Empty);
}
}
}
}
2-
public class A
{
private EventNotifier eventNotifier;
public EventNotifier MyEventNotifier { get { return eventNotifier; } }
public A()
{
eventNotifier = new EventNotifier();
}
}
3- Now your users of class A ( class which is inherited / composed class A)
this is for if B contains A
public class b
{
A obj ;
public b()
{
obj = new A();
obj.MyEventNotifier.OnChange += new EventHandler(delegate { Console.WriteLine("Hi"); });
obj. MyEventNotifier.HasChanged = true;
}
}
You could consider introducing an intermediary class between BaseClass and A,B,C that contains the common behaviour. In this way you will not be polluting E,F,G which do not need the behaviour.
BaseClass
-----------------------------
| |
----- NotifyBaseClass
E,F,G |
-----
A,B,C
NB Although AOP looks yummy I have had major problems trying to get Postsharp to work with other technologies e.g. MS Code Analysis and MSBuild.
Having a subclass for notifyable objects might be the way to go but it can be tricky with aspects multiplying that way into a wide range of different classes. Another way would to infact include it in your base class and define an interface for it, then you can simply tack on the interface for the relevant classes.
When running yous simply check if it's a IChangeable (or something) and only hook up to the event then
Related
I've made a class with T. It looks like this.
public interface ISendLogic<T> where T : NarcoticsResult
{
ChangeType Change_New();
ChangeType Change_Cancel();
PurchaseType Purchase_New();
PurchaseType Purchase_Cancel();
}
public class SendLogic<T> : ISendLogic<T> where T : NarcoticsResult
{
private eReportType _type;
private bool Send_Change()
{
// Send to server by xml file
}
private bool Send_Purchase()
{
// Send to server by xml file
}
public ChangeType Change_New()
{
_type = change_new;
Send_Change();
}
public ChangeType Change_Cancel()
{
_type = change_cancel;
Send_Change();
}
public PurchaseType Purchase_New()
{
_type = purchase_new;
Send_Purchase();
}
public PurchaseType Purchase_Cancel()
{
_type = purchase_cancel;
Send_Purchase();
}
}
There are two types, ChangeType and PurchaseType
and these are inherited from NarcoticsResult.
I thought the person who want to use this class would use it like this.
// this class can only be used when someone wants to use change function
var logic = SendLogic<ChangeType >();
logic.Change_New();
logic.Change_Cancel();
Here is a question.
I want to force this class to be used only as I thought.
I mean, I want to prevent it to be used like this.
var logic = SendLogic<ChangeType>();
logic.Change_New(); // OK
logic.Purchase_New(); // You should make this class like SendLogic<PurchaseType>()
I thought I add some code which check type of T in every function.
How do you think the way I thought. I think there are better way to fix it
Please tell me a better way
thank you.
Personally, I don't think you need a generic class in this case. What you need is either an abstract base class or an interface. I personally love the interface approach as below:
public interface ISendLogic {
void New();
void Cancel();
}
So now you've got a contract that will force the consumer of your code to use New or Cancel methods only.
The next step you can implement that send logic interface for your specific implementation:
public class ChangeSendLogic : ISendLogic {
private eReportType _type;
public ChangeSendLogic(
/*you can put the necessary parameters in the constructor
and keep it as private fields in the object*/
)
{
}
private bool Send_Change()
{
// Send to server by xml file
}
public void New()
{
_type = change_new;
Send_Change();
}
public void Cancel()
{
_type = change_cancel;
Send_Change();
}
}
public class PurchaseSendLogic : ISendLogic {
private eReportType _type;
public PurchaseSendLogic(
/*you can put the necessary parameters in the constructor
and keep it as private fields in the object*/
)
{
}
private bool Send_Purchase()
{
// Send to server by xml file
}
public void New()
{
_type = change_new;
Send_Purchase();
}
public void Cancel()
{
_type = change_cancel;
Send_Purchase();
}
}
From here you can see those two classes handle the implementation for each type nicely. You can think this is as an implementation of single responsibility principle. So if you have one more type, you can just add one more implementation of this interface rather than updating the existing classes.
If you want to hide the creation of those objects, in the next part you can introduce a kind of factory or selector as below:
public enum SendLogicType {
Change,
Purchase
}
public static SendLogicSelector {
public static ISendLogic GetSendLogic(SendLogicType type)
{
switch(type)
{
case SendLogicType.Change:
return new ChangeSendLogic();
case SendLogicType.Purchase:
return new PurchaseSendLogic();
}
}
}
This is how the code will be consumed:
ISendLogic sendLogic = SendLogicSelector.GetSendLogic(SendLogicType.Change);
sendLogic.New(); // change new logic executed
sendLogic.Cancel(); // change cancel logic executed
sendLogic = SendLogicSelector.GetSendLogic(SendLogicType.Purchase);
sendLogic.New(); // purchase new logic executed
sendLogic.Cancel(); // purchase cancel logic executed
Hopefully, you can get the idea of my approach. Good luck! :)
Thank you for your comment
I divided it into two parts like below
public class ChangeSendLogic : SendLogic<ChangeType>, IChangeLogic
public class PurchaseSendLogic : SendLogic<PurchaseType>, IPurchaseLogic
And I also divided interface too
public interface IChangeLogic
{
ChangeType Change_New();
ChangeType Change_Cancel();
}
public interface IPurchaseLogic
{
PurchaseType Purchase_New();
PurchaseType Purchase_Cancel();
}
And I made SendLogic<T> class to abstract class.
This is because I want to make the person who wants to use this class to use a class that inherits from this class without directly accessing it.
Thank you for your comment. I got a good idea.
I am stuck with a pattern for a long time now and recently I realized I forgot why I got used to do things this way.
public event EventHandler<string> SomethingChanged;
private void OnSomethingChanged(string something) => SomethingChanged?.Invoke(this, something);
So, when I want to invoke the event I call OnSomethingChanged(this, something);. Why not just do SomethingChanged?.Invoke(this, state); directly?
Feels like quite a simplification. Is it possible this OnSomethingChanged pattern served a purpose back then, when C# syntax was more complicated, but today it's mostly unnecessary?
In fact, since this pattern is quite long, I always just copy paste it and replace the relevant parts. Ironically, I can recall a couple of times when this copy pasting resulted debugging my software just to find out I made a mistake here, because of being in a hurry. This also makes invoking directly SomethingChanged preferable.
consider the following example:
public class BaseClass
{
private int id;
public int Id
{
get { return id; }
set { id = value; SomethingChanged(this, "id"); }
}
public event EventHandler<string> SomethingChanged;
}
public class DerivedClass : BaseClass
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
//// cannot be invoked directly here
// SomethingChanged(this, "name");
}
}
}
c# documentations mentions this case specifically
Events are a special type of delegate that can only be invoked from within the class that declared them. Derived classes cannot directly invoke events that are declared within the base class. Although sometimes you may want an event that can only be raised by the base class, most of the time, you should enable the derived class to invoke base class events. To do this, you can create a protected invoking method in the base class that wraps the event. By calling or overriding this invoking method, derived classes can invoke the event indirectly.
private method in the base class which triggeres event isn't much help, it should be protected. It is also sensible to make that method virtual to allow derived class add some functionality before/after notifing event subscrivers:
public class BaseClass
{
private int id;
public int Id
{
get { return id; }
set { id = value; OnSomethingChanged( "id"); }
}
public event EventHandler<string> SomethingChanged;
protected virtual void OnSomethingChanged(string something)
{
SomethingChanged(this, something);
}
}
public class DerivedClass : BaseClass
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
OnSomethingChanged("name");
}
}
protected override void OnSomethingChanged(string something)
{
base.OnSomethingChanged(something + " (event triggered from derived class)");
}
}
public static void Main(string[] args)
{
var item = new DerivedClass();
item.SomethingChanged += (e,s) => Console.WriteLine(s);
item.Id = 5;
item.Name = "abc";
}
this modified example prints:
id (event triggered from derived class)
name (event triggered from derived class)
How can I use C# generics to avoid having to create an extension function like so for each and every auto-generated class (Linq to SQL DBML)?
static public CharacterViewModel ToViewModel(this Character c)
{
return new CharacterViewModel(c);
}
Having a function like this provides a fairly clean way of selecting a set of items from the DB as their corresponding ViewModel, like so:
var characters = new ObservableCollection<CharacterViewModel>(from p in DB.Characters
select p.ToViewModel());
I'd like to see something like:
static public T ToViewModel<T,K>(K dbmlClass)
{
return new T(dbmlClass);
}
But I have a feeling this will involve Reflection-style object generation and I don't know how efficient that would be (or how to accomplish it).
By the way, I did previously investigate operator overloading the assignment ('=') as a possible solution, which could provide implicit casting, but I believe this would require overloading the = in the auto-generated class which I am not able to do.
Update
Thanks all, for the answers. I think I have a few avenues to check out now. To provide a bit more context, as some mentioned it wasn't clear. All of my ViewModels are derived from the following:
public class BaseDO<T>: BaseDO
{
public BaseDO(T model)
{
Model = model;
}
public T Model { get; set; }
}
abstract public class BaseDO: INotifyPropertyChanged, INotifyDeleted
{
#region Standard INotifyPropertyChanged Implementation
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged = (o, e) => { };
#endregion
public event EventHandler OnEntityDeleted = (o, e) => { };
public void NotifyEntityDeleted()
{
OnEntityDeleted(this, new EventArgs());
}
}
public interface INotifyDeleted
{
event EventHandler OnEntityDeleted;
void NotifyEntityDeleted();
}
You could use a library such as Automapper. With this you have 1 place where you setup the configuration of how objects are mapped. You can then have:
public static T ToViewModel<T,K>(K dbmlClass)
{
return AutoMapper.Mapper.Map<T>(dbmlClass);
}
// Register mappings
public static void ConfigureMappings()
{
AutoMapper.Mapper.CreateMap<Character, CharacterViewModel>();
}
It's not really clear from your question whether you want to generate the view model classes automatically or whether you've already written them and each one accepts the model as a constructor parameter. If the former then I personally add INPC to the model classes using either Castle Proxy or Frody. If the latter then I believe this is what you're after:
public static class Helper
{
static public T ToViewModel<T>(this object dbmlClass)
{
return (T)Activator.CreateInstance(typeof(T), dbmlClass);
}
}
Which you would then use like this:
var model = new Model();
var view_model = model.ToViewModel<ViewModel>();
In my app, I wanted to let class B get some information from class A but as A instantionates B, B has no reference to A (intentionally).
I have never used events for that purpose so I am not sure whether its correct, but it works:
class A
{
public delegate bool GetFromB();
public event GetFromB GetDataFromB;
...
//get data from B without having an access to it
bool Result=GetDataFromB();
}
class B
{
A a=new A();
A.GetDataFromB=new A.GetFromB(DO_THAT);
public bool DO_THAT()
{
...
return true; //and that is it, it will return to event caller
}
}
It'll certainly work, and that approach is used in a few places in the core framework - AssemblyResolve etc. Alternative approaches here:
if it is used by a method, pass it into the method as a callback delegate. Same approach, but simply not exposed as an event
ditto, but with an interface
but it'll work that way. It isn't unheard of. Code tweaks, though:
A a=new A();
a.GetDataFromB=+new A.GetFromB(DO_THAT);
you subscribe on the instance (unless it is static), and need +=, not =.
Also: consider using Func<bool> rather than declaring your own delegate type.
Don't do that. Events implies that multiple listeners can be used, and it looks like you are not handling return values from multiple listeners. You can do that by traversing myevent.GetInvocationList() and invoke each listener separately.
Use a simple delegate instead:
class A
{
public delegate bool GetFromB();
public GetFromB GetDataFromB { get; set; }
}
The other standard way is to have event arguments that provide a property for return value.
class MyEventArgs : EventArgs
{
public bool ReturnValue {get; set; }
// and something more here.
}
public class A
{
public event EventHandler<MyEventArgs> MyEvent;
}
As you wrote, A currently instanciates B so, you should not change this by creating an instance of A in B.
If B needs several different data from A, you can let A realize some IBNeededData interface. If B needs only one call on A, the straight forward solution would be a callback method.
Edit
Here's a sample for the callback. (Hope you are fine with the lambda expression to provide the data from A.)
[TestClass]
public class UnitTest1 {
class A {
public void DoWork() {
B b = new B();
//b.GetData = () => "Some data";
Func<string> callback = new Func<string>(this.GetBData);
b.GetData = callback;
b.DoBWork();
}
private string GetBData() {
return "Some data";
}
}
class B {
public Func<string> GetData { get; set; }
public void DoBWork() {
string data = GetData();
Console.WriteLine("Working with {0}", data);
}
}
[TestMethod]
public void TestMethod1() {
A a = new A();
a.DoWork();
}
}
C# - .net 3.5
I have a family of classes that inherit from the same base class.
I want a method in the base class to be invoked any time a property in a derrived class is accessed (get or set). However, I don't want to write code in each and every property to call the base class... instead, I am hoping there is a declarative way to "sink" this activity into the base class.
Adding some spice to the requirement, I do need to determine the name of the property that was accessed, the property value and its type.
I imagine the solution would be a clever combination of a delegate, generics, and reflection. I can envision creating some type of array of delegate assignments at runtime, but iterating over the MemberInfo in the constructor would impact performance more than I'd like. Again, I'm hoping there is a more direct "declarative" way to do this.
Any ideas are most appreciated!
You can't do it automatically, but you can pretty much get 95% for free. This is a classic case for aspect-oriented programming. Check out PostSharp, which has the OnFieldAccessAspect class. Here's how you might solve your problem:
[Serializable]
public class FieldLogger : OnFieldAccessAspect {
public override void OnGetValue(FieldAccessEventArgs eventArgs) {
Console.WriteLine(eventArgs.InstanceTag);
Console.WriteLine("got value!");
base.OnGetValue(eventArgs);
}
public override void OnSetValue(FieldAccessEventArgs eventArgs) {
int i = (int?)eventArgs.InstanceTag ?? 0;
eventArgs.InstanceTag = i + 1;
Console.WriteLine("value set!");
base.OnSetValue(eventArgs);
}
public override InstanceTagRequest GetInstanceTagRequest() {
return new InstanceTagRequest("logger", new Guid("4f8a4963-82bf-4d32-8775-42cc3cd119bd"), false);
}
}
Now, anything that inherits from FieldLogger will get the same behavior. Presto!
I don't believe this is possible to do declaratively, i have never seen it done that way. What you can do though is implement the INotifyPropertyChanged interface on your base class, and have the implementation of the interface in the base class. Something like this:
public class A : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
protected virtual void RaiseOnPropertyChanged(object sender, string propertyName)
{
if (this.PropertyChanged != null)
PropertyChanged(sender, new PropertyChangedEventArgs(propertyName);
}
public A()
{
this.PropertyChanged += new PropertyChangedEventHandler(A_PropertyChanged);
}
void A_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//centralised code here that deals with the changed property
}
}
public class B : A
{
public string MyProperty
{
get { return _myProperty; }
set
{
_myProperty = value;
RaiseOnPropertyChanged(this, "MyProperty");
}
}
public string _myProperty = null;
}