I have created an Attribute, call MyAttribute, which is performing some security and for some reason the Constructor is not being fired, any reason why?
public class Driver
{
// Entry point of the program
public static void Main(string[] Args)
{
Console.WriteLine(SayHello1("Hello to Me 1"));
Console.WriteLine(SayHello2("Hello to Me 2"));
Console.ReadLine();
}
[MyAttribute("hello")]
public static string SayHello1(string str)
{
return str;
}
[MyAttribute("Wrong Key, should fail")]
public static string SayHello2(string str)
{
return str;
}
}
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
public MyAttribute(string VRegKey)
{
if (VRegKey == "hello")
{
Console.WriteLine("Aha! You're Registered");
}
else
{
throw new Exception("Oho! You're not Registered");
};
}
}
Attributes are applied at compile time, and the constructors used only to fill in the properties. Attributes are metadata, and can only be examined at runtime.
In fact, Attributes should not contain any behavior at all.
Actually it fails, but only if you are trying to get attribute properties. Here is an example that fails:
using System;
public class Driver
{
// Entry point of the program
public static void Main(string[] Args)
{
Console.WriteLine(SayHello1("Hello to Me 1"));
Console.WriteLine(SayHello2("Hello to Me 2"));
Func<string, string> action1 = SayHello1;
Func<string, string> action2 = SayHello2;
MyAttribute myAttribute1 = (MyAttribute)Attribute.GetCustomAttribute(action1.Method, typeof(MyAttribute));
MyAttribute myAttribute2 = (MyAttribute)Attribute.GetCustomAttribute(action2.Method, typeof(MyAttribute));
Console.ReadLine();
}
[MyAttribute("hello")]
public static string SayHello1(string str)
{
return str;
}
[MyAttribute("Wrong Key, should fail")]
public static string SayHello2(string str)
{
return str;
}
}
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
public string MyProperty
{
get; set;
}
public string MyProperty2
{
get;
set;
}
public MyAttribute(string VRegKey)
{
MyProperty = VRegKey;
if (VRegKey == "hello")
{
Console.WriteLine("Aha! You're Registered");
}
else
{
throw new Exception("Oho! You're not Registered");
};
MyProperty2 = VRegKey;
}
}
Related
I have a class
public class MyCoolProp
{
public string FullName {get;set;}
}
and in another Class i have this as Property:
public class MyMainClass
{
public MyCoolProp coolprop {get;set;}
public void DoSomething()
{
MessageBox.Show(nameof(coolprop.FullName));
}
}
The Actual Result is: "Fullname"
But i want a combination like this: "coolprop.FullName"
i dont want to do something like this:
nameof(coolprop) + "." + nameof(coolprop.FullName);
Maybe its possible in an extension?
If i rename the Property "coolprop" the output should also have the new name
Depending on exactly what you want to do, you might be able to use CallerArgumentExpressionAttribute. That does mean you need to be willing to actually evaluate the property as well, even if you don't use it.
Note that this requires a C# 10 compiler.
Here's a complete example:
using System.Runtime.CompilerServices;
public class MyCoolProp
{
public string FullName { get; set; }
}
class Program
{
static MyCoolProp CoolProp { get; set; }
static void Main()
{
CoolProp = new MyCoolProp { FullName = "Test" };
WriteTextAndExpression(CoolProp.FullName);
}
static void WriteTextAndExpression(string text,
[CallerArgumentExpression("text")] string expression = null)
{
Console.WriteLine($"{expression} = {text}");
}
}
Output: CoolProp.FullName = Test
Source:
get name of a variable or parameter (modified a bit adjusted with your case)
You can use what System.Linq.Expression provides
code example:
using System.Linq.Expression
class Program
{
public static MyCoolProp coolProp { get; set; }
static void Main(string[] args)
{
coolProp = new MyCoolProp() { FullName = "John" };
DoSomething();
}
public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.ToString();
}
public static void DoSomething()
{
string prop = GetMemberName(() => coolProp.FullName);
Console.WriteLine(prop);
}
}
public class MyCoolProp
{
public string FullName { get; set; }
}
the GetMemberName method will return the namespace, class name, object name, and variable name (depends where the method is being called)
Output: Program.coolProp.FullName
I want the value to be initialized according to the attribute When Instance is created.
class FieldAttr : Attribute
{
public readonly string key;
public Key_FieldAttr(string key)
{
this.key = key;
}
}
class CtorAttr : Attribute
{
}
static string FromTable(string key)
{
// will return localized string of key from table.
}
...
class LocalizedMetadata
{
[FieldAttr("NAME")]
public string Name { get; }
[FieldAttr("DESC")]
public readonly string Description;
[CtorAttr]
public LocalizedMetadata(string header)
{
// I want "Key" attribute to do as below...
// this.Name = FromTable(header + "NAME");
// this.Description = FromTable(header + "DESC");
}
}
public static void Main(string[] args)
{
var foo = new LocalizedMetadata("UNITY_");
Console.WriteLine(foo.Name); // = FromTable("UNITY_NAME");
Console.WriteLine(foo.Description); // = FromTable("UNITY_DESC");
}
I don't know where to attach what kind of Attribute (Field, Construction, Class) will be possible.
I looked up documents about Attribute and Reflection, but I don't know if this is possible.
I think below solution will solve your problem.
class LocalizedMetadata
{
[FieldAttr("NAME")]
public string Name { get; set; }
[FieldAttr("DESC")]
public string Description { get; set; }
public LocalizedMetadata(string header)
{
foreach (var property in typeof(LocalizedMetadata).GetProperties())
{
foreach (var attr in property.GetCustomAttributes(false))
{
FieldAttr fieldAttr = (FieldAttr)attr;
property.SetValue(this, header + fieldAttr.Key);
}
}
}
}
public static void Main(string[] args)
{
var foo = new LocalizedMetadata("UNITY_");
Console.WriteLine(foo.Name);
Console.WriteLine(foo.Description);
}
Output:
UNITY_NAME
UNITY_DESC
I have a DTO that looks like this:
public class MyDto
{
[MyAttribute("attribute1")]
public string Property1 {get;set;}
[MyAttribute("attribute2")]
public string Property2 {get;set;}
}
If I have the string "attribute1", how do I use that to get to the value of Property1 in an instance of MyDto?
Use Reflection. Unfortunately, there's no way to obtain the property from an attribute: you have to iterate through each property and check its attribute.
Not the most robust code, but try this:
public class MyAttributeAttribute : Attribute
{
public MyAttributeAttribute(string value)
{
Value=value;
}
public string Value { get; private set; }
}
public class MyDto
{
[MyAttribute("attribute1")]
public string Property1 { get; set; }
[MyAttribute("attribute2")]
public string Property2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
MyDto dto=new MyDto() { Property1="Value1", Property2="Value2" };
string value=GetValueOf<string>(dto, "attribute1");
// value = "Value1"
}
public static T GetValueOf<T>(MyDto dto, string description)
{
if(string.IsNullOrEmpty(description))
{
throw new InvalidOperationException();
}
var props=typeof(MyDto).GetProperties().ToArray();
foreach(var prop in props)
{
var atts=prop.GetCustomAttributes(false);
foreach(var att in atts)
{
if(att is MyAttributeAttribute)
{
string value=(att as MyAttributeAttribute).Value;
if(description.Equals(value))
{
return (T)prop.GetValue(dto, null);
}
}
}
}
return default(T);
}
}
Let's assume that I have this scenario: I have got 2 repositories of information, and I want to access both, but it would be nice to leave the task of deciding which repo to use to common class.
The goal is to accomplish this with something similar to the code I've wrote below, but this sounds pretty bad:
where TOnline : class
where TOffline : class
where TContract : class
Sure I can ommit that, but bassically what I'm asking is what to do in order to stop using reflection and go typed. Maybe any design-pattern recomendation?
Code (if you copy/paste this on a console app replacing the Program class you should be able to run the example)
using CustomerDispatcher = DispatcherProxy<CustomerOnline, CustomerOffline, ICustomer>;
public interface ICustomer
{
string Get(int id);
}
public class CustomerOnline : ICustomer
{
public string Get(int id)
{
// Get From intranet DB
return "From DB";
}
}
public class CustomerOffline : ICustomer
{
public string Get(int id)
{
// Get From local storage
return "From local storage";
}
}
public class DispatcherProxy<TOnline, TOffline, TContract>
where TOnline : class
where TOffline : class
where TContract : class
{
public TContract Instance { get; set; }
public bool IsConnected { get; set; }
public DispatcherProxy()
{
// Asume that I check if it's connected or not
if (this.IsConnected)
this.Instance = (TContract)Activator.CreateInstance(typeof(TOnline));
else
this.Instance = (TContract)Activator.CreateInstance(typeof(TOffline));
}
}
class Program
{
static void Main(string[] args)
{
var customerDispatcher = new CustomerDispatcher();
Console.WriteLine("Result: " + customerDispatcher.Instance.Get(1));
Console.Read();
}
}
Thanks in advance!
You can add the new() constraint:
public class DispatcherProxy<TOnline, TOffline, TContract>
where TOnline : class, new()
where TOffline : class, new()
where TContract : class //isn't TContract an interface?
{
public TContract Instance { get; set; }
public bool IsConnected { get; set; }
public DispatcherProxy()
{
// Asume that I check if it's connected or not
if (this.IsConnected)
this.Instance = new TOnline() as TContract;
else
this.Instance = new TOffline() as TContract;
}
}
In case any of you are interested, I had to change the way I did this because it was checking connection at Constructor Level, and I needed that check at Operation Level.
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
namespace ConsoleApplication1
{
public enum ConnectionStatus
{
Online,
Offline,
System // System checks connectivity
}
public static class Connectivity
{
private static ConnectionStatus ConnectionStatus = ConnectionStatus.Offline;
public static void ForceConnectionStatus(ConnectionStatus connectionStatus)
{
ConnectionStatus = connectionStatus;
}
public static bool IsConnected()
{
switch (ConnectionStatus)
{
case ConnectionStatus.Online:
return true;
case ConnectionStatus.Offline:
return false;
case ConnectionStatus.System:
return CheckConnection();
}
return false;
}
private static bool CheckConnection()
{
return true;
}
}
public class Unity
{
public static IUnityContainer Container;
public static void Initialize()
{
Container = new UnityContainer();
Container.AddNewExtension<Interception>();
Container.RegisterType<ILogger, OnlineLogger>();
Container.Configure<Interception>().SetInterceptorFor<ILogger>(new InterfaceInterceptor());
}
}
class Program
{
static void Main(string[] args)
{
Unity.Initialize();
var r = new Router<ILogger, OnlineLogger, OnlineLogger>();
Connectivity.ForceConnectionStatus(ConnectionStatus.Offline);
Console.WriteLine("Calling Online, will attend offline: ");
r.Logger.Write("Used offline.");
Connectivity.ForceConnectionStatus(ConnectionStatus.Online);
Console.WriteLine("Calling Online, will attend online: ");
r.Logger.Write("Used Online. Clap Clap Clap.");
Console.ReadKey();
}
}
public class Router<TContract, TOnline, TOffline>
where TOnline : TContract
where TOffline : TContract
{
public TContract Logger;
public Router()
{
Logger = Unity.Container.Resolve<TContract>();
}
}
public interface IOnline
{
IOffline Offline { get; set; }
}
public interface IOffline
{
}
public interface ILogger
{
[Test()]
void Write(string message);
}
public class OnlineLogger : ILogger, IOnline
{
public IOffline Offline { get; set; }
public OnlineLogger()
{
this.Offline = new OfflineLogger();
}
public void Write(string message)
{
Console.WriteLine("Online Logger: " + message);
}
}
public class OfflineLogger : ILogger, IOffline
{
public IOnline Online { get; set; }
public void Write(string message)
{
Console.WriteLine("Offline Logger: " + message);
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
public class TestAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new TestHandler();
}
}
public class TestHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("It's been intercepted.");
if (!Connectivity.IsConnected() && input.Target is IOnline)
{
Console.WriteLine("It's been canceled.");
var offline = ((input.Target as IOnline).Offline);
if (offline == null)
throw new Exception("Online class did not initialized Offline Dispatcher.");
var offlineResult = input.MethodBase.Invoke(offline, this.GetObjects(input.Inputs));
return input.CreateMethodReturn(offlineResult, this.GetObjects(input.Inputs));
}
return getNext()(input, getNext);
}
private object[] GetObjects(IParameterCollection parameterCollection)
{
var parameters = new object[parameterCollection.Count];
int i = 0;
foreach (var parameter in parameterCollection)
{
parameters[i] = parameter;
i++;
}
return parameters;
}
}
}
// stupid title, but I could not think anything smarter
I have a code (see below, sorry for long code but it's very-very simple):
namespace Option1
{
class AuxClass1
{
string _field1;
public string Field1
{
get
{
return _field1;
}
set
{
_field1 = value;
}
}
// another fields. maybe many fields maybe several properties
public void Method1()
{
// some action
}
public void Method2()
{
// some action 2
}
}
class MainClass
{
AuxClass1 _auxClass;
public AuxClass1 AuxClass
{
get
{
return _auxClass;
}
set
{
_auxClass = value;
}
}
public MainClass()
{
_auxClass = new AuxClass1();
}
}
}
namespace Option2
{
class AuxClass1
{
string _field1;
public string Field1
{
get
{
return _field1;
}
set
{
_field1 = value;
}
}
// another fields. maybe many fields maybe several properties
public void Method1()
{
// some action
}
public void Method2()
{
// some action 2
}
}
class MainClass
{
AuxClass1 _auxClass;
public string Field1
{
get
{
return _auxClass.Field1;
}
set
{
_auxClass.Field1 = value;
}
}
public void Method1()
{
_auxClass.Method1();
}
public void Method2()
{
_auxClass.Method2();
}
public MainClass()
{
_auxClass = new AuxClass1();
}
}
}
class Program
{
static void Main(string[] args)
{
// Option1
Option1.MainClass mainClass1 = new Option1.MainClass();
mainClass1.AuxClass.Field1 = "string1";
mainClass1.AuxClass.Method1();
mainClass1.AuxClass.Method2();
// Option2
Option2.MainClass mainClass2 = new Option2.MainClass();
mainClass2.Field1 = "string2";
mainClass2.Method1();
mainClass2.Method2();
Console.ReadKey();
}
}
What option (option1 or option2) do you prefer ? In which cases should I use option1 or option2 ? Is there any special name for option1 or option2 (composition, aggregation) ?
According to Law of Demeter, Option2. That way you can freely change the implementation of MainClass, You don't have to worry about calling code relying on details of AuxClass1, and indeed can remove it entirely if needed.
EDIT
interface IAuxClass1
{
string Field1 { get; set; }
void Method1();
void Method2();
}
class AuxClass1 : IAuxClass1
{
string _field1;
public string Field1
{
get
{
return _field1;
}
set
{
_field1 = value;
}
}
// another fields. maybe many fields maybe several properties
public void Method1()
{
// some action
}
public void Method2()
{
// some action 2
}
}
public class MyClass : ServiceContainer
{
public MyClass()
{
this.AddService(typeof(IAuxClass1), new AuxClass1());
}
public MyClass(IAuxClass1 auxClassInstance)
{
this.AddService(typeof(IAuxClass1), auxClassInstance);
}
public IAuxClass1 AuxClass
{
get
{
return (this.GetService(typeof(IAuxClass1)) as IAuxClass1);
}
}
}
Original
I tihnk MainClass should derive from AuxClass..
class MainClass : AuxClass1
{
}
I would start with implementing a nice feature of C# called "automatic properties". Instead of writing
private ThisType _myThing;
public ThisType MyThing
{
get { return _myThing; }
set { _myThing = value; }
}
you can write
public ThisType MyThing { get; set; }
and the compiler will generate the exact same IL. On top of this, you can add some options, for example making the setter private:
public ThisType MyThing { get; private set; }
In your case, I would go for option 3:
namespace Option3
{
public AuxClass
{
public string Field1 { get; set; }
public Method1() { ... }
public Method1() { ... }
}
public MainClass
{
public AuxClass Aux { get; private set; }
public MainClass(AuxClass aux)
{
this.Aux = aux;
}
}
}
class Program
{
static void Main(string[] args)
{
Option3.AuxClass = auxClass3 = new Option3.AuxClass();
Option3.MainClass mainClass3 = new Option3.MainClass(auxClass3);
mainClass3.Aux.Field1 = "string2";
mainClass3.Aux.Method1();
mainClass3.Aux.Method2();
}
}
This way, you lock the AuxClass reference once it's set (like in Option 2) while not locking up yourself for changes in the AuxClass interface (like in Option 1).
Decision of choosing design is based on different factors,
Shorter code => Option 1
Monitor activity of each functionality and every access => Option 2, however using linq and expressions, you can write a generalized code that can work with even option 1, but thats too complicated to discuss here.