C# Custom attributes passed down to called methods - c#

Is there a way to get custom attributes which are added along the flow? I'm adding custom attributes to different methods in different classes that are called depending on the flow. I've tried MethodBase.GetCurrentMethod() but this (as it says) only the current invoked method. Using new StackFrame(n) also doesn't work since "n" can frequently change. Googled my problem but didn't find any hints.
public class CustomAttribute1 : Attribute
{
public bool Property { get; }
public CustomAttribute1(bool property) => Property = property;
}
public class CustomAttribute2 : Attribute
{
public string Property { get; }
public CustomAttribute2(string property) => Property = property;
}
public class GeneralService
{
protected void Resolve()
{
// Here I want to access custom attributes combined
}
}
public class SpecifiedService : GeneralService
{
[CustomAttribute1(true)]
public void SendRequest()
{
Resolve();
}
}
public class Worker
{
[CustomAttribute2("init")]
public void Init()
{
var service = new SpecifiedService();
service.SendRequest();
}
}

Related

How do I don't validate a nested class in FluentValidation MVC

I have a Viewmodel that have another Viewmodel inside, take a look
[Validator(typeof(ParentValidatorVM))]
public class ParentVM {
public ChildVM { get; set; }
public ParentVM () {
this.ChildVM = new ChildVM ();
}
}
//rulles for validation
internal sealed class ParentValidatorVM : AbstractValidator<ParentVM> {
public ParentValidatorVM() {
//set rules
this.RuleFor(x => x.ChildVM).NotValidate();
//the row above is just an example the method 'NotValidate', I invented
}
}
The ChildVM has the structure with properties
[Validator(typeof(ChildValidatorVM))]
public class ChildVM {
//My properties
}
//rulles for validation
internal sealed class ChildValidatorVM : AbstractValidator<ChildVM> {
public ChildValidatorVM() {
//set rules
}
}
My problem is, when I call ModelState.isValid the rules from the child comes together the rules from the Parent, it is not to happen.
Someone know a way to avoid it?

How do I assign a value to a WebViewPage property from a filter or a controller?

After reading this question and its answer: How to set ViewBag properties for all Views without using a base class for Controllers? I have created a custom WebViewPage with an extra property on it:
public abstract class MyWebViewPage<TModel> : WebViewPage<TModel>
{
protected MyObject MyProperty { get; set; }
}
public abstract class MyWebViewPage: MyWebViewPage<dynamic> { }
This has worked well, and the property is now accessible and correctly typed when I use it in any of my views. But now I'd like to automatically assign a value to this property from an ActionFilter, how do I access the instance of "MyWebViewPage" from the filter in order to assign to that property?
You can assign your value into ViewData and get this data from the getter of your property.
namespace NorthWindMVC.Views
{
public abstract class TestViewPage<TModel> : WebViewPage<TModel>
{
protected string TestProperty
{
get { return ViewData["TestProperty"] != null ? ViewData["TestProperty"].ToString() : String.Empty; }
set { ViewData["TestProperty"] = value; }
}
}
public abstract class TestViewPage : TestViewPage<dynamic>
{
}
}
And in your filter,
namespace NorthWindMVC.Filters
{
public class TestActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.Controller.ViewData["TestProperty"] = "mahmut";
}
}
}

Overrideable property that can be accessed both by instance and by class

I have an inheritance tree with a bunch of different classes. Each of these classes has some static properties that I need acces to from time to time. Sometimes I need the property of a particular class, and sometimes I need the property of the specific class some polymorphic instance turns out to be.
This would be easy in, say, Java (I think). Just make a bunch of static fields (can these be overriden? I'm not sure). But in C#, non-static fields can ONLY be accessed via an instance (naturally), and static fields can ONLY be accessed via their corresponding class (unnaturally).
And, you can't "overload" by, er, staticity. If a class has a static and a non static Foo, doing instance.Foo fails because it is unclear to the compiler which Foo you're referring to even though it's impossible you're referring to the static one since it's disallowed.
Ok, I'll provide some code. Say I have this:
class Base
{
public static readonly string Property = "Base";
}
class Child1 : Base
{
public static readonly new string Property = "Child 1";
}
class Child2 : Base
{
public static readonly new string Property = "Child 2";
}
And then, somewhere:
public void SomeMethod(Base instance)
{
System.Console.WriteLine(instance.Property); // This doesn't work.
}
And somewhere else:
public void SomeOtherMethod()
{
System.Console.WriteLine(Child2.Property);
}
I want something like that, that actually works.
As Peter Duniho said, this can be done with reflection.
For example, these can be defined within the base class:
public const string Property = "Base";
public virtual string InstanceProperty
{
get
{
return (string)this.GetType()
.GetField("Property", BindingFlags.Public | BindingFlags.Static)
.GetValue(null);
}
}
And then each derived class just has to redefine Property using the new keyword.
I think the best you'll do in C# is something like this:
public class BaseClass
{
public virtual string InstanceProperty
{
get { return StaticProperty; }
}
public static string StaticProperty
{
get { return "BaseClass"; }
}
}
public class Derived1Base : BaseClass
{
public override string InstanceProperty
{
get { return StaticProperty; }
}
public new static string StaticProperty
{
get { return "Derived1Base"; }
}
}
public class Derived1Derived1Base : Derived1Base
{
}
public class Derived2Base : BaseClass
{
public override string InstanceProperty
{
get { return StaticProperty; }
}
public new static string StaticProperty
{
get { return "Derived2Base"; }
}
}

Interface, Inheritance, and C#

I'm designing a data layer for several classes, and I want each of these classes to follow a contract I set up with IMyDataItem:
public delegate void ItemChangedHandler(object sender, EventArgs e);
public interface IMyDataItem<T> {
string Insert { get; }
int Save();
string Select { get; }
string Update { get; }
}
That being done, I now want to include a base class that my other classes all inherit from.
How would I fix this base class?
public class MyDataItem : IMyDataItem<T> {
private const string TODO = "TODO: This has not been done.";
public const int NOT_SET = -1;
private bool changed;
internal int rowId;
public MyDataItem() {
changed = false;
rowId = NOT_SET;
}
public ItemChangedHandler OnChange;
internal void notify() {
changed = true;
if (OnChange != null) {
OnChange(this, new EventArgs());
}
}
public int RowID {
get { return rowId; }
set {
if (rowId != value) {
rowId = value;
notify();
}
}
}
public bool SaveNeeded { get { return changed; } }
public static virtual T Load() {
return default(T);
}
public virtual string Insert { get { return TODO; } }
public virtual string Select { get { return TODO; } }
public virtual string Update { get { return TODO; } }
public virtual int Save() {
changed = false;
return NOT_SET;
}
}
The errors are all in the second class MyDataItem (my base class):
Type or namespace name 'T' could not be found - on the first line where I declare my class.
I tried removing the errors by adding a where clause to the signature:
public class MyDataItem : IMyDataItem<T> where T : MyDataItem {
However, this presented me with the error:
Constraints are not allowed on non-generic declarations
Is there a way to do what I am after, or will I need to stick with simpler class designs?
When the base class is complete, other classes such as Location, Employee, and Record will inherit it.
Well to fix that particularly compile time error you would need:
public class MyDataItem<T> : IMyDataItem<T>
However, without knowing more about what you're trying to achieve, it's hard to recommend an alternative approach.
Why not drop the <T> from the interface and make it non-generic? The T is not used in the interface.
Otherwise, if you want the class to be generic, say
public class MyDataItem<T> : IMyDataItem<T>
But again, if T is not used, what's your reason to declare it?
What you are attempting to do is somewhat similar to what I've also done. I've wanted some generic code applicable to all my "data manager" instances but also wanted to apply stronger typing to them... In a similar fashion...
public interface iMyDataManager
{
stuff ...
}
public class MyDataManager<T> : iMyDataManager
{
implementation ... that I want common to all derived specific instances
}
public class MySpecificDataInstance : MyDataManager<MySpecificDataInstance>
{
continue with rest of actual implementations specific to this class.
}
I did not see any reason use generic in your implementation.
Secondary, are you sure about parameters of these functions:
string Insert { get; }
int Save();
string Select { get; }
string Update { get; }
Why Update and Insert returns parameters? Are you sure, you will able remember meaning of this within 2 months?

How can I wrap static properties of a base class so that they return a sub class object?

Say I have code out there like this:
public class Base // I cannot change this class
{
public string Something { get; private set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
// How can I wrap the PreSets here so that they return SubClass objects?
// Something like this:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
}
}
}
What makes this complicated is the Something property. It has a private setter. So I can't set it in the subclass. The only way it can be set is is via the preset properties.
Is there a way to wrap the StaticPreSet property in my SubClass so that it will return an object of type SubClass?
// I cannot change this base class.
Given that you can't change the base class, there is no way to cause it to change behavior (ie: return a different class at runtime).
If you could influence the design of the base class static methods, you could redesign it in a way to be flexible enough to provide this functionality. However, without changing it, this won't work.
Edit in response to edit:
You could create a new static method that does what you are showing, like so:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
Base baseInstance = Base.StaticPreSet;
SubClass sc = new SubClass(baseInstance); // Create a new instance from your base class
return sc;
}
}
However, this provides a completely new, unrelated property - you'd have to access it via SubClass.MyWrappedPreset, not the Base class.
Static fields in a class "have nothing to do with it".
Basically, except access to private static fields, id doesn't matter in which class you put them - they behave the same.
If you inherit a class, and you declare another static field with the same name of a static field on the base class, you will simply 'hide' it. Example for you:
using System;
public class Base // I cannot change this class
{
public string Something { get; set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
public static SubClass StaticPreSet2
{
get { return new SubClass { Something = "inherited", Otherthing=""}; }
}
}
public class Test
{
public static void Main()
{
Console.WriteLine(SubClass.StaticPreSet2.Something);
}
}
Will write "inherited".

Categories