Mono.Cecil: How to replace base class - mono.cecil

I have some classes Like the following:
public class MvxEventSourceActivity : Activity
{
protected override void MethodA()
{
DoSomething();
base.MethodA();
}
}
public class MvxActivity : MvxEventSourceActivity
{
...
}
There are a bunch of different subclasses of Activity and right now I have to make an MvxEventSource/MvxActivity pair for each one (Example: MvxEventSourceListActivity/MvxListActivity that wraps the class ListActivity which inherits from Activity. If I was using C++ I could use CRTP to do something like the following:
public class MvxEventSourceActivity<TActivity> : TActivity
where TActivity : Activity
{
protected override void MethodA()
{
DoSomething();
base.MethodA();
}
}
public class MvxActivity : MvxEventSourceActivity<Activity>
{
...
}
But this is C# and I can't do that. How would I go about using Fody to do something like that?

Related

Unable to use protected method override in Acumatica Graph Extension

I'm attempting to create a graph extension to modify the behavior of one of the mobile scan screens, and I found in developer release notes for 2020 R1 the ability to use the [PXProtectedAccess] attribute to utilize protected members of a Graph from the extension, even though it does not directly inherit from it.
However, in order to utilize this, the Graph Extension class needs to be abstract and Acumatica no longer seems to recognize it when I do so. I'm sure that I am missing a crucial piece here but I can't figure out what it is based on documentation. EDIT: I was missing the [PXProtectedAccess] attribute on the class itself.
Now I am seeing something else when I try to actually call the abstract method. It throws Unable to cast object of type 'Wrapper.PX.Objects.IN.Cst_INScanIssueHost' to type 'INScanIssueHostDynamicInterface'. when I attempt to call any one of these protected members. I'm not sure what INScanIssueHostDynamicInterface refers to or how to resolve the type conflicts here.
Here is an excerpt of the code I'm using:
[PXProtectedAccess]
public abstract class INScanIssue_Extension : PXGraphExtension<INScanIssue, INScanIssueHost>
{
[PXProtectedAccess]
protected abstract void ReportError(string errorMsg, params object[] args);
public delegate void ProcessConfirmDelegate();
[PXOverride]
public virtual void ProcessConfirm(ProcessConfirmDelegate baseMethod)
{
ReportError("TEST");
}
}
I think you are on the right path. Your graphExtension should be abstract. Also please note that on your extension you use protected member of the graph extension by specifying the parameter of the attribute, as shown below:
public class MyGraph : PXGraph<MyGraph>
{
protected void Bar() { }
}
public class MyExt : PXGraphExtension<MyGraph>
{
protected void Foo() { }
}
[PXProtectedAccess]
public abstract class MySecondLevelExt : PXGraphExtension<MyExt, MyGraph>
{
[PXProtectedAccess]
protected abstract void Bar();
[PXProtectedAccess(typeof(MyExt))]
protected abstract void Foo();
}
So in your case, I think you can try to add that parameter to the ProctectedAccess attribute for those members that from INScanIssue(or overriden there ):
namespace PX.Objects.IN
{
[PXProtectedAccess]
public abstract class INScanIssue_Extension : PXGraphExtension<INScanIssue,
INScanIssueHost>
{
public static bool IsActive()
{
return true;
}
# region Protected Access
*[PXProtectedAccess(typeof(INScanIssue))]*
protected abstract void ClearHeaderInfo(bool redirect = false);
[PXProtectedAccess]
protected abstract void SetScanState(string state, string message = null, params object[] args);
[PXProtectedAccess(typeof(INScanIssue))]
protected abstract bool PromptLocationForEveryLine { get; }
........................................
Use the abstract extension only to access the protected members, then add a second level extension, that calls the exposed members from your first level extension. And I don't think you need to apply the attribute on the extension.
public abstract class INScanIssueProtectedAccessExt : PXGraphExtension<INScanIssue, INScanIssueHost>
{
[PXProtectedAccess]
public abstract void ReportError(string errorMsg, params object[] args);
}
public class INScanIssue_Extension : PXGraphExtension<INScanIssueProtectedAccessExt, INScanIssue, INScanIssueHost>
{
public delegate void ProcessConfirmDelegate();
[PXOverride]
public virtual void ProcessConfirm(ProcessConfirmDelegate baseMethod)
{
this.Base2.ReportError("TEST");
}
}

Map to specific derived type based on value on source using Automapper

I'm having trouble implementing Automapper conversion in a situation where the source is a class which should be mapped to one of two derived classes based on a value on the source.
Here's a simplification of my classes:
public class FooContainerDTO
{
public FooDTO Foo { get; set; }
}
public class FooDTO
{
public string Type { get; set; }
//some properties..
}
public class FooContainer
{
public FooBase Foo { get; set; }
}
public abastract class FooBase
{
//some properties..
}
public class FooDerived1 : FooBase
{
//some properties
}
public class FooDerived2 : FooBase
{
//some properties
}
I'm using non-static Automapper so I create a MapperConfiguration from several Profiles at boot and inject the IMapper instance into my DI-container.
I want Automapper to map FooDTO to FooDerived1 when its Type property is "der1" and to FooDerived2 when it is "der2".
I've seen examples on this using the static api, something like this:
Mapper.CreateMap<FooContainerDTO, FooContainer>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooDerived1>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooDerived2>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooBase>()
.ConvertUsing(dto => dto.Type == "der1"
? (FooBase) Mapper.Map<FooDerived1>(dto)
: Mapper.Map<FooDerived2>(dto));
This would map the Foo property of FooContainer to the correct derived type of FooBase.
But how can I do this without the static API?
The IMapper instance is not yet created at the point of configuring the profile.
Is there a way to leverage the overload of ConvertUsing() which takes a Func< ResolutionContext,object >? Can the resolution context give me whatever IMapper is currently being used? I've been looking, but can't find anything usable.
One way to get access to the mapping engine is via your own TypeConverter
abstract class MyTypeConverter<TSource,TDestination> : ITypeConverter<TSource, TDestination>
{
protected ResolutionContext context;
public TDestination Convert(ResolutionContext context)
{
this.context = context;
return Convert((TSource)context.SourceValue);
}
public abstract TDestination Convert(TSource source);
}
You then create an actual implementation like:
class MyTypeMapper : MyTypeConverter<EnumType,EnumTypeView>
{
public override EnumTypeView Convert(EnumType source)
{
return context.Engine.Mapper.Map<EnumTypeID, EnumTypeView>(source.EnumBaseType);
}
}
Except instead of unwrapping an enum structure, you'd check the type and call Map with different types.

MS TEst: Method not executed when base class is generic

Not duplicate of: Inherited test class from generic base is ignored in MSTest
In my case, the test classes are in the same namespace/assembly.
When unittesting classes which have a lot in common, I would like to use a base test class with a generic parameter. I have boiled the problem down to the following, where my base test method is not being executed, but ONLY in the generic case.
Non-generic: Base test method is EXECUTED:
[TestClass]
public class DerivedTestClass : BaseUnitTest
{
protected override string ReturnMeSomething(object obj)
{
return "test1" + obj.ToString();
}
[TestMethod]
public void derived_test()
{
// This is executed
}
}
[TestClass]
public abstract class BaseUnitTest
{
[TestMethod]
public void base_test()
{
// This is executed
}
protected abstract string ReturnMeSomething(object obj);
}
Generic: Base test method in generic base class is NOT EXECUTED:
[TestClass]
public class DerivedTestClass : BaseUnitTest<string>
{
protected override string ReturnMeSomething(string s)
{
return "test1" + s;
}
[TestMethod]
public void derived_test()
{
// This is executed
}
}
[TestClass]
public abstract class BaseUnitTest<T>
{
[TestMethod]
public void base_test()
{
// This is NOT executed
}
protected abstract string ReturnMeSomething(T t);
}
Can anyone tell me the reason for this?
After a few days, this suddenly works (!!). If anyone ever experiences this same, odd behavior, please write a comment here. I would suggest anyone to reboot and clean+rebuild everything and try again.

Postsharp - Adding OnMethodBoundaryAspect to abstract Method - Aspect Not Firing

I'm trying to implement an OnMethodBoundary aspect on an abstract method in an abstract class so that all types that inherit from this class will automatically have the aspect applied. There are no compilation errors or warnings, but the OnEntry method doesn't fire. Note: If I apply the aspect to a non-abstract method, everything works fine
here's the aspect example:
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, Inheritance = MulticastInheritance.Multicast)]
public sealed class DoSomethingAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
//Do work
}
}
// here's the abstract class
public abstract class Job
{
//...
[DoSomething]
public abstract void Run();
}
Updated answer: it doesn't matter where anything is, as long as both projects have Postsharp referenced then you're good to go.
It works just fine. Which version of PostSharp are you using?
class Program
{
static void Main(string[] args)
{
Job1 j = new Job1();
j.Run();
Console.ReadKey();
}
}
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, Inheritance = MulticastInheritance.Multicast)]
public sealed class DoSomethingAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("OnEntry");
}
}
public abstract class Job
{
//...
[DoSomething]
public abstract void Run();
}
public class Job1 : Job
{
public override void Run()
{
Console.WriteLine("Run method");
}
}
Results:
OnEntry
Run method

Optional component functionality vs SRP

I have a design issue that I encounter currently.
Let's say there is a hierarchy of components. Each of these component derives from an abstract Component type which looks something like this:
public abstract class Component
{
public abstract Component Parent { get; }
public abstract ComponentCollection Children { get; }
}
Now I want to add some optional functionality to those components, lets take being able to search within the component hierarchy and to select components within the hierarchy as examples.
Is it considered bad practice to provide those optional functionality in the base class like this:
public abstract class Component
{
// Other members
public abstract bool IsSearchable { get; }
public abstract bool Search(string searchTerm);
public abstract bool IsSelectable { get; }
public abstract bool Select();
}
While the "search-ability" and "select-ability" is managed in derived components by e.g. using strategy patterns?
Somehow this seems like violation of the SRP to me, but in my opinion the only alternative would be to have an interface for each optional functionality and only implement it on components that support this functionality.
In my opinion this would have the drawback that I have to write code like this everytime I want to check if a component provides specific functionality:
public bool Search(Component component, string searchTerm)
{
ISearchable searchable = component as ISearchable;
if(searchable != null)
{
searchable.Search(searchTerm);
}
}
Which strategy would you choose or do you have any better ideas?
Thanks in advance!
A possible option:
If the searchability/selectability implementation is provided through the strategy pattern (dependency injection), as you say, then I think interfaces for ISearchable and ISelectable are a better idea.
You can derive your strategy object from these interfaces, and implement getters for them in your base-Component class - GetSearchable(), GetSelectable() - where the default implementation in Component returns null (or a no-op implementation of the interface if you dislike null).
Why don't you use decorator?
Component c = new Component ();
var selectableAndSearchableOne = new SelectableComponent (new SearchableComponent (c));
Ok another one: this time you also know the component's extension points. with a visitor-like pattern
public interface IHasExtensions
{
List<Extension> Extensions { get; }
void Extend (Extension ext);
}
public class Component : IHasExtensions
{
List<Extension> exts = new List<Extension> ();
public List<Extension> Extensions
{
get { return exts; }
}
public void Extend (Extension ext)
{
exts.Add (ext);
}
void Draw() { }
}
public abstract class Extension
{
readonly protected Component _Component;
public Extension(Component component)
{
_Component = component;
}
}
public class SearchExtension : Extension
{
public SearchExtension (Component component) : base (component)
{
}
}
public class SelectionExtension : Extension
{
public SelectionExtension (Component component) : base (component)
{
}
}
public class test_fly
{
void start ()
{
Component c = new Component ();
c.Extend (new SearchExtension (c));
c.Extend (new SelectionExtension (c));
var exts = c.Extensions; // I Know the extensions now
}
}

Resources