I have an abstract class used for caching that implements as follows (simplified)
public abstract class DataCacheMember<T> : List<T>
{
private List<T> _data;
public List<T> Data
{
get
{
if (_data == null || _data.Count() < 1)
_data = GetData();
return _data;
}
}
private string ApiEndPoint {get; set;}
private Timer timer;
private List<T> GetData()
{
//call api and get data
}
private void RefreshData()
{
_data = GetData();
}
protected DataCacheMember(string apiEndPoint)
{
ApiEndPoint = apiEndPoint;
timer = new System.Threading.Timer(
e => RefreshData(),
null,
TimeSpan.Zero,
TimeSpan.FromMinutes(10));
}
}
It allows for rapid creation of cached objects with a simple string for the api endpoint:
public class StateMap<Properties> : DataCacheMember<Properties>
{
public StateMap(string apiEndPoint = "Property/GetProperties")
: base(apiEndPoint)
{}
}
The whole reason for inheriting from List<T> was to remove the need for the fields.
However, if I try to modify the constructor and refresh to:
private void RefreshData()
{
this = GetData() as DataCacheMember<T>;
}
protected DataCacheMember(string apiEndPoint)
{
this = GetData() as DataCacheMember<T>;
}
I get an error of Cannot assign to <this> because it is Read Only.
What's the proper way to resolve this? Do I just need to use Clear() and AddRange() to manage the object?
If I do that, I see that the first call to the object will return empty, because the object can return before the constructor finishes it's call.
To answer the question you cannot assign this in a constructor or any other method. You could add the items returned from GetData():
private void RefreshData()
{
this.Clear();
this.AddRange(GetData());
}
protected DataCacheMember(string apiEndPoint)
{
this.Clear();
this.AddRange(GetData());
}
But inheriting form List<T> probably isn't the right design here.
According to Using this() in C# Constructors
private void RefreshData()
{
this = GetData() as DataCacheMember<T>;
}
protected DataCacheMember(string apiEndPoint)
{
this = GetData() as DataCacheMember<T>;
}
These would only work in a struct and doesn't really do anything useful and is bad design.
Related
I have a static array list in class called cart, is there a way to implement event listener to be used by other classes?
I am new to c# tried to understand PropertyChangedEventHandler with no success.
The arraylist and property are initialized as below:
private static ArrayList cartList = new ArrayList();
public static ArrayList CartList
{
get { return cartList; }
set
{
cartList = value;
}
}
Edit:
Altered #KMC code to work with List by hiding base methods:
public class ListOfProducts : List<Product>
{
public void Add(Product obj)
{
base.Add(obj);
this.OnChange();
}
public void UpdateLast(Product obj)
{
base[base.Count - 1] = obj;
this.OnChange();
}
public void Remove(Product obj)
{
base.Remove(obj);
this.OnChange();
}
public void Clear()
{
base.Clear();
this.OnChange();
}
public event EventHandler Change;
protected void OnChange()
{
if (this.Change != null)
{
this.Change(this, new EventArgs() { });
}
}
}
the ArrayList type is extensible. you can override the add and remove methods and fire some events.
for ex)
public class NewArrayList : ArrayList
{
public event EventHandler Change;
public override int Add(object value)
{
var result = base.Add(value);
this.OnChange();
return result;
}
public override void Remove(object obj)
{
base.Remove(obj);
this.OnChange();
}
protected void OnChange()
{
if (this.Change != null)
{
this.Change(this, new EventArgs() { });
}
}
}
public static class program
{
static void Main(string[] args)
{
var list = new NewArrayList();
list.Change += delegate (object sender, EventArgs arg) {
Console.WriteLine("collect changed {0}", list.Count);
};
list.Add(1);
list.Add(2);
list.Remove(2);
}
}
since the ArrayList needs to send some type of message (event) and I'm not sure who will be receiving it, I'll leave it up to you.
You can't get notified when count of elements in ArrayList changes nor when any element changes.
ArrayList and most other standard collections in .Net Framework like List<T>, Dictionary and arrays (except specialized classes like ObservableCollection in WPF) do not provide notification on items added/removed. You can easily check that by looking at MSDN entry for corresponding class and see if it implements INotifyCollectionChanged and/or INotifyPropertyChanged. I.e. ArrayList only implements IList, ICollection, IEnumerable, ICloneable and no notification interfaces.
If you need notification of such change you should create your own class with such notification or use ObservableCollection.
Side note: please consider using List<T> instead of non-generic ArrayList- ArrayList vs List<> in C#.
I need to add the following to several unrelated classes:
private MyClass myclass;
private EventHandler clicked;
public event EventHandler Clicked { ... }
private bool enabled;
public bool Enabled { ... }
private void HandleClicked(object sender, EventArgs e) { ... }
The problem is these classes are third-party and do not necessarily share the same immediate base class though they all eventually inherit from a class called View. Right now, I end up creating my own subclasses for each and copy-pasting the same code which leads to unnecessary duplication.
Any way to meaningfully refactor this?
One of the way is to use composition. Create class which will store all new events\properties\methods:
public class Properties
{
private MyClass myclass;
private EventHandler clicked;
public event EventHandler Clicked { ... }
private bool enabled;
public bool Enabled { ... }
private void HandleClicked(object sender, EventArgs e) { ... }
}
Then use Extension methods to expand required interface (i.e. classA)
public static class NewInterfaces
{
public static Properties Props(this classA)
{ /* lookup required properties, from some associative storage */ }
}
Usage will look like:
var inst = new classA();
inst.Prop.Enabled = !inst.Prop.Enabled;
Second way it still composition, but you will use wrapper for those:
public class Wrapper
{
private object _wrapped;
public Wrapper(classA obj)
{
_wrapped = obj;
}
public Wrapper(classB obj)
{
_wrapped = obj;
}
public int WrappedProperty
{
get
{
var instA = _wrapped as classA;
if (instA != null)
return instA.SomeProperty1;
var instB = _wrapped as classB;
if (instB != null)
return instB.SomeProperty2;
}
}
private MyClass myclass;
private EventHandler clicked;
public event EventHandler Clicked { ... }
private bool enabled;
public bool Enabled { ... }
private void HandleClicked(object sender, EventArgs e) { ... }
}
Second way allow you to create new hierarchy of wrapper which will contain elements without common base class.
Inheritance becomes problematic in time. I recommend using interfaces instead, you will have much more flexibility.
public interface INewInterfaces
{
event EventHandler Clicked;
bool Enabled { get; }
void HandleClicked(object sender, EventArgs e);
}
public class NewClassA : ClassA, INewInterfaces
{
//...
}
public class NewClassB : ClassB, INewInterfaces
{
//...
}
Edit 1:
If you are saying that ClassX's are very similar and you want to use the same HandleClicked implementation in all of these unrelated classes, you may use two other approaches.
1- Still inheritance
Create an interface and add all the common functions across the classes you want to use. This will put the ClassX's in the same family. And then create a class for general use.
public interface IExistingInterfaces
{
void SomeMethod();
}
public class NewClassA : ClassA, IExistingInterfaces
{
//Do nothing
}
public class NewClassB : ClassB, IExistingInterfaces
{
//Do nothing
}
public class MyClassForGeneralUse : IExistingInterfaces
{
private IExistingInterfaces _baseObject;
public MyClassForGeneralUse(IExistingInterfaces baseObject)
{
_baseObject = baseObject;
}
//Write proxy calls for IExistingInterfaces
public void SomeMethod()
{
_baseObject.SomeMethod();
}
//Add new methods here
public void HandleClicked(object sender, EventArgs e)
{
}
//...
//...
}
Not: The first part is Bridge Pattern and the second part is Decorator Pattern
2- Reflection
var propertyInfo = someObject.GetType().GetProperty("property name");
if (propertyInfo == null)
throw new Exception(string.Format("Property does not exist:{0}", condition.Property));
var propertyValue = propertyInfo.GetValue(someObject, null);
long longValue = (long)propertyValue;
//You can get methods in a smilar manner and execute with
result = methodInfo.Invoke(methodInfo, parametersArray);
But reflection may be overkill.
I need to make alternative to List<> class where I will have 4 methods... Two for adding int items, one from front, other from behind and two for deleting, one from front and other from behind as well. My class should not inherit anything.
Something like this...
public class MyList
{
public void AddItemsFront(int pItem)
{
}
public void AddItemsBehind(int pItem)
{
}
public void DeleteItemsFront(int pItem)
{
}
public void DeleteItemsBehind(int pItem)
{
}
}
You could hold an instance of a List<T> in a field, List<T> has already these methods:
public class MyList<T>
{
private List<T> _TheList;
public MyList()
{
_TheList = new List<T>();
}
public List<T> TheList { get { return _TheList; } set { _TheList = value; } }
public void AddItemFront(T pItem)
{
TheList.Insert(0, pItem);
}
public void AddItemBehind(T pItem)
{
TheList.Add(pItem);
}
public void DeleteItemFront()
{
TheList.RemoveAt(0);
}
public void DeleteItemBehind()
{
TheList.RemoveAt(TheList.Count - 1);
}
}
Since it's a generic class you could also use it for different types than int.
var myList = new MyList<int>();
myList.AddItemFront(1);
Create a class that's got a data member of the correct List<> type, and implement your methods by calling the appropriate methods on the List<> data member. You will want your delete operations to return the object they removed from the list.
This is often referred to as the Adapter pattern. Wikipedia has a page on it.
I'm trying to expose an API such that, I do the following
RegisterCallback<T>(Action<T> func)
{
someObj.FuncPointer = func;
}
Later on, I call func(obj) .. and the obj is of type T that the user said.
More concrete example:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
public static void SomeFunc(ISomeClass data)
{
//
}
EDIT: So I may not have been clear, so I'll add more code:
I want to make only "one" object of CBRegistrar, and connect it with many Callbacks, as such:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
callbackRegistrar.RegisterCallback<ISomeOtherClass>(SomeFunc2);
...
In fact the above code is called by reflecting over a directory of plugins.
The user puts this in their code -->
public static void SomeFunc(ISomeClass data)
{
//
}
public static void SumFunc2(ISomeOtherClass data)
{
//
}
It looks to me as if this is not possible using Generics, etc. What it looks like I might have to do is make an interface called IPlugin or something, and ask the user to do this ..
[PluginIdentifier(typeof(ISomeClass))]
public static void SomeFunc(IPluginData data)
{
var castedStuff = data as ISomeClass; // ISomeClass inherits from IPluginData
}
Seems like asking the user to do stuff that we should take care of, but anyway ...
You need a Action<T> func to store it in. There is a semantic check to make here: if someone calls RegisterCallback twice (with different values), do you want to replace the callback, or keep both ? Assuming the latter, someObj probably wants an event (indeed, this entire API could be exposed as an event), so - in the someObj class:
public event Action<T> FuncPointer;
private void InvokeCallback(T data) {
var handler = FuncPointer;
if(handler != null) handler(data);
}
Noting that RegisterCallback could be replaced entirely, still keeping the data on obj:
public event Action<T> Completed {
add { obj.FuncPointer += value; }
remove { obj.FuncPointer -= value; }
}
Then usage would be:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.Completed += SomeFunc;
Callback functions are not much used in C#. They've been replaced by events which are more elegant and easier to work with.
class CBRegistrar
{
public delegate void ActionRequiredEventHandler(object sender, ISomeClass e);
public event ActionRequiredEventHandler ActionRequired;
void RaiseActionRequiredEvent(ISomeClass parm)
{
if ( ActionRequired != null)
{
ActionRequired(this, parm);
}
}
}
class APIConsumer
{
var callbackRegistrar = new CBRegistrar();
public APIConsumer()
{
callbackRegistrar.ActionRequired += SomeFunc;
}
public void SomeFunc(object sender, ISomeClass data)
{
}
}
If you still want to use Callbacks, you can use Delegates which are more or less function pointer.
The CBRegistrar will need to be generic (if it's OK to keep a single callback type) or it can do some internal casting (if several callback types need to be registered).
public class CBRegistrar<T>
{
private Action<T> callback;
private Dictionary<Type, object> callbackMap;
public CBRegistrar()
{
this.callbackMap = new Dictionary<Type, object>();
}
public void RegisterCallback(Action<T> func)
{
this.callback = func;
}
public void RegisterGenericCallback<U>(Action<U> func)
{
this.callbackMap[typeof(U)] = func;
}
public Action<U> GetCallback<U>()
{
return this.callbackMap[typeof(U)] as Action<U>;
}
}
public interface ISomeClass
{
string GetName();
}
public class SomeClass : ISomeClass
{
public string GetName()
{
return this.GetType().Name;
}
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
var callbackRegistrar = new CBRegistrar<ISomeClass>();
callbackRegistrar.RegisterCallback(SomeFunc);
callbackRegistrar.RegisterGenericCallback<ISomeClass>(SomeFunc);
var someone = new SomeClass();
callbackRegistrar.GetCallback<ISomeClass>()(someone);
}
public static void SomeFunc(ISomeClass data)
{
// Do something
Console.WriteLine(data.GetName());
}
}
}
I am not sure if I understood the usage of delegates correctly but I would like to read delegate return value in publisher class. The example is below with description.
//Publisher class
public class ValidateAbuse
{
public delegate List<String> GetAbuseList();
public static GetAbuseList Callback;
public void Ip(string ip)
{
// I would like to read GetAbuseList value (List<String>) here. How to do that?
}
}
//Subscriber class
class Server
{
public static void Start()
{
ValidateAbuse.Callback = GetIpAbuseList;
ValidateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return List<String> to ValidateAbuse class and use return value in public void Ip(string ip) method
}
public void Ip(string ip)
{
if (Callback != null)
{
List<String> valueReturnedByCallback = Callback();
}
}
Here's a version that does not use static for ValidateAbuse and that uses the built-in Func<T> delegate.
public class ValidateAbuse
{
private Func<List<string>> callback;
public ValidateAbuse(Func<List<string>> callback)
{
this.callback = callback;
}
public void Ip(string ip)
{
var result = callback();
}
}
public class Server
{
public static void Start()
{
var validateAbuse = new ValidateAbuse(GetIpAbuseList);
validateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return List<string> to ValidateAbuse class and use return value in public void Ip(string ip) method
}
}
I recommend you avoid static since that gives you a global state, which could later give you coupling problems and also makes it hard for you to unit test.
The other answers given so far has a guard clause, checking Callback for null. Unless that is expected behaviour (that Callback is null) I would avoid this. It's better to crash early than to get hard to debug errors later on.
I would also try to make the Server non-static.
It should be as simple as:
// Ip in your code sample is missing static
public static void Ip(string ip)
{
List<string> abuseList;
if (Callback != null)
abuseList = Callback()
}
However you can avoid creating a delegate all together by using a Func:
public static Func<List<string>> Callback;
Try this: Read more from here http://msdn.microsoft.com/en-us/library/bb534960%28v=vs.110%29.aspx
internal delegate int PowerOfTwo();
void Main(){
PowerOfTwo ch = new PowerOfTwo(CheckPower);
Console.WriteLine(ch());
}
int CheckPower(){
return 2*2;
}
#Torbjörn Kalin's answer is good, but only if you have only 1 delegate you want to get the return value from. If you want to retrieve the return values of more than one delegate, this is how you do it:
//Publisher class
public class ValidateAbuse
{
public delegate List<String> GetAbuseList();
public static GetAbuseList Callback;
public void Ip(string ip)
{
foreach (GetAbuseList gal in Callback.GetInvocationList())
{
List<string> result = gal.Invoke(/*any arguments to the parameters go here*/);
//Do any processing on the result here
}
}
}
//Subscriber class
class Server
{
public static void Start()
{
//Use += to add to the delegate list
ValidateAbuse.Callback += GetIpAbuseList;
ValidateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return code goes here
return new List<String>();
}
This will invoke each delegate one after the other, and you can process the output of each delegate separately from each other.
The key here is using the += operator (not the = operator) and looping through the list that is retrieved by calling GetInvocationList() and then calling Invoke() on each delegate retrieved.
I figured this out after reading this page:
https://www.safaribooksonline.com/library/view/c-cookbook/0596003390/ch07s02.html
(altho it was partially because I already had an idea what to do, and I didn't start a free trial to read the rest)
Hope this helps!