Extending a delegate from a base class
I'd either create a wrapper delegate to make it the correct type in SubClass
.
class SubClass: BaseClass {
var myDelegate: SubClassDelegate? {
get { return delegate as? SubClassDelegate }
set { delegate = newValue }
}
@IBAction func onDoSomething(sender: AnyObject) {
myDelegate?.additionalSubClassDelegateMethod();
}
}
Or simply cast the delegate to the expected type:
(delegate as? SubClassDelegate)?.additionalSubClassDelegateMethod();
Is it at all possible to extend System.Delegate?
Not with your own custom code, in C#. From section 10.1.4 of the C# 3.0 spec:
The direct base class of a class type
must not be any of the following
types:System.Array
,System.Delegate
,
System.MulticastDelegate
,System.Enum
,
orSystem.ValueType
. Furthermore, a
generic class declaration cannot use
System.Attribute
as a direct or
indirect base class.
However, every time you create a delegate type, that automatically derives from MulticastDelegate
.
From ECMA-335, section 8.9.3:
While, for the most part, delegates
appear to be simply another kind of
user-defined class, they are tightly
controlled. The implementations of the
methods are provided by the VES, not
user code. The only additional members
that can be defined on delegate types
are static or instance methods.
That sounds like it's prohibiting constructors. I'd use a static method in a normal type instead, personally.
Using params in a Delegate as a base class
based on your updated code -- try this. As long as your method matches the delegate the contravariance should work as expected in .NET 3.5 or better
public abstract class SKConsoleParameter
{
protected string value;
public SKConsoleParameter(string value)
{
this.value = value;
}
public string GetRawValue()
{
return value;
}
public abstract bool IsValid();
public abstract object GetValue();
}
public class StringParam : SKConsoleParameter
{
public StringParam(string value) : base(value) { }
public override bool IsValid()
{
return true;
}
public override object GetValue()
{
return value;
}
}
public class IntParam : SKConsoleParameter
{
public IntParam(string value) : base(value) { }
public override bool IsValid()
{
int i;
return int.TryParse(value, out i);
}
public override object GetValue()
{
int i;
if (int.TryParse(value, out i))
return i;
else
return 0;
}
}
class Program
{
public delegate void CoolDelegate(params SKConsoleParameter[] parameters);
static void Main(string[] args)
{
var s = new StringParam("Glenn");
var i = new IntParam("12");
var coolDel = new CoolDelegate(DoSomethingCool);
coolDel(s, i);
}
public static void DoSomethingCool(params SKConsoleParameter[] parameters)
{
if (parameters == null) throw new ArgumentNullException("parameters");
foreach (var item in parameters)
{
if (item is IntParam)
{
// do something interesting
continue;
}
if (item is StringParam)
{
// do something else interesting
continue;
}
throw new NotImplementedException("unknown param type");
}
}
}
Delegate with base and/or inherited class parameter
Stumbled upon a blog that identified a solution that works. https://faithlife.codes/blog/2008/07/casting_delegates/
Excerpt from blog: "Fortunately, it is possible to cast between arbitrary delegate types, though it isn’t as efficient as you might like."
public static class DelegateUtility {
public static T Cast<T>(Delegate source) where T : class {
return Cast(source, typeof(T)) as T;
}
public static Delegate Cast(Delegate source, Type type) {
if (source == null)
return null;
Delegate[] delegates = source.GetInvocationList();
if (delegates.Length == 1)
return Delegate.CreateDelegate(type,
delegates[0].Target, delegates[0].Method);
Delegate[] delegatesDest = new Delegate[delegates.Length];
for (int nDelegate = 0; nDelegate < delegates.Length; nDelegate++)
delegatesDest[nDelegate] = Delegate.CreateDelegate(type,
delegates[nDelegate].Target, delegates[nDelegate].Method);
return Delegate.Combine(delegatesDest);
}
}
Using their utility class, i was able to cast the delegate type to it's base class which worked.
lstComplexThings [i].OnDoesStuff += DelegateUtility.Cast<Action<MyMoreComplexThing>>(callback);
Inject delegate method from derived to base class using constructor
The main thing I would suggest to change is:
- to replace
AnotherDelegateMethod
andAnotherOneDelegateMethod
passing (and then calling from parent class) with corresponding virtual methods.
As for another things, that all depends on the logic your class is suppose to implement. Possibly, some more decoupling might be needed.
new AnotherRepository(ADelegateMethod). That's really a tough question how to do everything right -- more info about general logic would be needed, as different approaches possible:
- you can replace that also with virtual methods, like ADelegateMethod -- the same way as mentioned two above, but new AnotherRepository as
protected virtual ISomeRepositoryInterface CreateRepositoryInstance()
(for instance); you can use dependency injection into some outside classes which would use your handler to pass the the repository, the same, actually, as Tools or another repository (but, again, everything depends on the general logic);
one of the ways to customize your handler(s) is to make the basic class as Generic and to inherit the children with providing some concrete class, which logic is related exactly to the inheritor, but mostly used only in parent class.
- you can replace that also with virtual methods, like ADelegateMethod -- the same way as mentioned two above, but new AnotherRepository as
About events:
- I would recommend you to read something like this and generally get familiar with Rx (Reactive Extensions) -- they are modern and awesome (you can consider using them instead of events in many cases (if not in this handler class, then in some other situations)). (However, currently I can't see the situation when you really would need to use events in your class).
Also, as for @durilka's answer (however, that's really funny to trust him considering his nickname "liar" from Russian, he he): he mentioned correctly (before I got into that) about:
- to remove the nested class and replace with static constructor (if in base class). But that must be carefully rethinked (especially, if you really use multithreading widely).
Related Topics
Screen Recording When My iOS App Is in Background with Replaykit
Change Duration (Speed) on a Running Animation
Swift: Obtain and Save the Updated Scnnode Over Time Using Projectpoint in Scenekit
What Is the Simplest Way to Retrieve the Device Serial Number of an iOS Device Using Monotouch
Cgaffinetransformmakerotation with Negative M_Pi
Swift3 Random Extension Method
Routing Between Points with Mapbox
Load Offline Cached JSON Using Afnetworking
Uiimageview .Scaleaspectfit and Autolayout Not Working Programmatically from Swift
Swift/How to Call Delegate with Popviewcontroller
Scaling Physics Bodies in Xcode Spritekit
What Is a Safe Way to Turn Streamed (Utf8) Data into a String
Swift iOS Record Video and Audio with Avfoundation
Can't Copy File from Bundle to Documents Directory in iOS