Ninject interception attribute with parameters passed to interceptor? - c#

I have interception working currently (very simplistically) with the following code:
(see question at bottom)
My Interceptor:
public interface IAuthorizationInterceptor : IInterceptor { }
public class AuthorizationInterceptor : IAuthorizationInterceptor
{
public IParameter[] AttributeParameters { get; private set; }
// This doesnt work currently... paramters has no values
public AuthorizationInterceptor(IParameter[] parameters) {
AttributeParameters = parameters;
}
public void Intercept(IInvocation invocation) {
// I have also tried to get the attributes like this
// which also returns nothing.
var attr = invocation.Request.Method.GetCustomAttributes(true);
try {
BeforeInvoke(invocation);
} catch (AccessViolationException ex) {
} catch (Exception ex) {
throw;
}
// Continue method and/or processing additional attributes
invocation.Proceed();
AfterInvoke(invocation);
}
protected void BeforeInvoke(IInvocation invocation) {
// Enumerate parameters of method call
foreach (var arg in invocation.Request.Arguments) {
// Just a test to see if I can get arguments
}
//TODO: Replace with call to auth system code.
bool isAuthorized = true;
if (isAuthorized == true) {
// Do stuff
}
else {
throw new AccessViolationException("Failed");
}
}
protected void AfterInvoke(IInvocation invocation) {
}
}
My Attribute:
public class AuthorizeAttribute : InterceptAttribute
{
public string[] AttributeParameters { get; private set; }
public AuthorizeAttribute(params string[] parameters) {
AttributeParameters = parameters;
}
public override IInterceptor CreateInterceptor(IProxyRequest request) {
var param = new List<Parameter>();
foreach(string p in AttributeParameters) {
param.Add( new Parameter(p, p, false));
}
// Here I have tried passing ConstructorArgument(s) but the result
// in the inteceptor constructor is the same.
return request.Context.Kernel.Get<IAuthorizationInterceptor>(param.ToArray());
}
}
Applied to a method:
[Authorize("test")]
public virtual Result<Vault> Vault(DateTime date, bool LiveMode = true, int? SnapshotId = null)
{
...
}
This works, and I am able to pass additional parameters through the attribute like this:
[Authorize("test")]
If you'll noticed in my attribute I am grabbing some parameters from the attribute, which I am able to access in the attribute class, but I am unable to pass those to the Interceptor. I have tried using the ConstructorArgument in the Kernel.Get<>() call, which doesnt throw an error, but the AuthorizationInterceptor constructor doesnt get any values from ninject. I have also tried GetCustomAttributes() as you can see in the code sample but this also returns nothing. From looking at other similar posts like this (Ninject Interception 3.0 Interface proxy by method attributes) that seems to be the correct way, but it doesn't work. Any ideas?

I was able to get something working by creating an initialization method on the interceptor. I don't really like it, because it ties me to the specific implementation of AuthorizationInterceptor, but it gets the job done (damn deadlines lol). I would still like to know if there is a better way to do this, so I am not going to mark my own answer in hopes that somebody comes along with a better way of doing this.
I modified the attribute as follows:
public override IInterceptor CreateInterceptor(IProxyRequest request) {
AuthorizationInterceptor attr = (AuthorizationInterceptor)request.Context.Kernel.Get<IAuthorizationInterceptor>();
attr.Init(AttributeParameters);
return attr;
}
And created an Init method on the the interceptor:
public void Init(params string[] parameters) {
AttributeParameters = parameters;
}

Related

C# Optional<TObject> as a return type?

Often i have a method where i want to return the error if something goes wrong, and instead of returning null, I want something less prone to errors at runtime and more easy to consume. Is there anything already done in .Net or maybe a nuget package?
Maybe have a constructor with optional parameters or object initializer would be enough?
This would have been the first approach but then every new Dto has to either have these Error property or inherit from a base class.
if (condition)
{
return new MyDto(null, error);
}
return new MyDto(someVariable, null);
So I've made this class to use a return type:
public class Optional<TObject> where TObject : class
{
public Optional(TObject? value)
{
Value = value;
}
public Optional(String error)
{
Error = error;
}
public TObject? Value { get; }
public String Error { get;} = String.Empty;
public Boolean IsError => !String.IsNullOrEmpty(Error);
}
I return it in the method:
if (condition)
{
return new Optional(error);
}
return new Optional(new MyDto(someVariable));
And then consume it like this:
var result = await myService.GetSomethingAsync();
if(result.IsError)
{
await DisplayAlert("error", result.Error, "Ok");
}
else
{
await DoSomethingElse(result.Value);
}
By creating a small class hierarchy, you could ensure that the Value property is only available when no error occurred
public abstract class Result
{
public virtual string Message => null;
public static Error Error(string message) => new Error(message);
public static Okay<T> Okay<T>(T value) where T : class => new Okay<T>(value);
}
public class Error : Result
{
public Error(string errorMessage) => Message = errorMessage;
override public string Message { get; }
}
public class Okay<T> : Result
where T : class
{
public Okay(T value) => Value = value;
public T Value { get; }
}
Usage
Result result = Result.Error("Something went wrong");
// OR
Result result = Result.Okay(new MyDto(someVariable));
if (result is Okay<MyDto> dtoResult) {
Console.WriteLine(dtoResult.Value);
} else {
Console.WriteLine(result.Message);
}
Or by using a recursive pattern, we can retrieve the value into a variable directly
if (result is Okay<MyDto> { Value: var dto }) {
Console.WriteLine(dto);
} else {
Console.WriteLine(result.Message);
}
Note that I have declared the Message property in the abstract base class Result, so that you don't have to cast to the Error type to get the message.
I used null as defualt value for the error message, as it allows us to write
Console.Writeline(result.Message ?? "okay");
This OneOf recommendation you got looks promising. I will personally have a look at it later.
What I do with my services is to standardize the result they return by using a SvcResult class or an inherited class.
Example:
public class SvcResult
{
public List<Error> Errors { get; } // Error is a class of my own. Add set; if deserialization is needed.
public bool Success { get; } // Add set; if deserialization is needed.
// Then parameterless constructor for a successful result.
// Then parameterized constructor to receive errors for a failed result.
}
That is the class for side-effect service calling. If The service returns data, I derive from the above to create DataSvcResult:
public class DataSvcResult<TResult> : SvcResult
{
public TResult Data { get; }
// Add constructor that receives TResult for a successful object result.
// Expose base class constructor that takes errors.
}
Basically that's what I do. But that OneOf thing, though. Looks super intersting.

How to get generic type from one class to another c#

Is it possible to pass the generic type from one class to other class generic property.
For example:
Assembly Logger
namespace Logger
{
public class GenericLoger<T>
{
T _genericLog;
LogManager _logManager;
public GenericLoger(string logName)
{
_logManager = new LogManager(logName);
//Assigning the generic type to Log.GenerciLog, this is how I am
expecting or by some other possible way?.
Log.GenerciLog = _genericLog;
}
public static Write(string description)
{
_logManager.write(description);
}
}
public static class Log
{
LogManager _logManager;
static Log()
{
_logManager = new LogManager();
}
public static Write(string description)
{
_logManager.write(description);
}
//The generic type supplied in GenericLoger need to pass here,
//like this or by some other possible way?
public static T GenerciLog { get; internal set; }
//T is unrecognized here as type is available in GenericLoger
//I want to pass here from GenericLoger
}
}
Assembly Main Caller of Logger
using Logger;
namespace DataProcessor
{
internal class SpecialLogger
{
private static Lazy<GenericLog<SpecialLogger>> _passed;
public static GenericLog<SpecialLogger> Passed
{
get
{
if (_passed == null)
{
_passed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Passed"), true);
}
return _passed.Value;
}
}
private static Lazy<GenericLog<SpecialLogger>> _failed;
public static GenericLog<SpecialLogger> Failed
{
get
{
if (_failed == null)
{
_failed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Failed"), true);
}
return _failed.Value;
}
}
}
internal class Processor
{
public void ProcessRate()
{
var trans = dataManager.GetData();
//Will write the log in "Log.txt" file
Log.write(trans.Count + " transaction found");
foreach (var item in trans)
{
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' property I want to access like this
Log.GenerciLog.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' property I want to access like this
Log.GenerciLog.Failed.Write(item);
}
}
}
}
}
NOTE: In .NET you don't have a way for automatic type inference for use case like yours, also there is no automatic type substitution.
Not sure if this is what you are looking for
Your method definition should look like this
public static T GenerciLog<T> { get; internal set; }
and this is how to call it
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Failed.Write(item);
}
This is a very simple log class. There is a lot more you could do with this sort of thing. Its all provided by log4net which I'd recommend using rather than trying to write your own logger. But the below is a start of how I'd implement a simple logger. It allows you to log to several different things at once. I appreciate the below doesn't answer exactly what you want but its an indication of how to start and you can adapt it to suit your needs.
public static class Logger
{
private static List<ILogger> _loggers = new List<ILogger>();
public static void Log(string message)
{
foreach (var logger in _loggers)
logger.Write(message);
}
public static void AddLogger(ILogger logger)
{
_loggers.Add(logger);
}
}
public interface ILogger
{
void Write(string message);
}
public class SpecialLogger : ILogger
{
public void Write(string message)
{
//special log code here eg
Console.WriteLine(message);
}
}
then somewhere do this
Logger.AddLogger(new SpecialLogger());
Logger.Log("A log message");

How to check for parameter type?

I've made my own Ajax "generic" (cant remember how you call this principle in C#) like this (only relevant functions):
public class Ajax<T>
{
public delegate void CallbackAjaxFinished(T j);
public void Get(string Url, CallbackAjaxFinished cbAjaxFinished)
{
/* blablah launch the Ajax call which calls back GetFinished() below */
}
private void GetFinished(HTTPRequest request, HTTPResponse response)
{
ConvertThenCallback(response, true);
}
private void ConvertThenCallback(HTTPResponse response, bool isGet)
{
try {
/* make conversion, T could be for example class JsonData */
j = (T)JsonUtility.FromJson<T>(response.DataAsText);
} catch (ArgumentException) { /* Conversion problem */
return;
}
}
}
That was working well, like this:
Ajax<JsonState> a = new Ajax<JsonState>();
a.Get(
baseURL + _urlGetState, /* get Url */
/* callback Ajax finished: */
(JsonState j) => { /* do stuff in the callback */ }
);
The problem is that Unity's JsonUtility doesnt handle nested arrays (...).
To make a long story short, I'd like in my "generic" stuff, to pass a custom "json decode" function callback, default=null, and in the ConvertThenCallback() function, do this:
if there's no custom function, call j = (T)JsonUtility.FromJson<T>(response.DataAsText); (like it already is now)
if there's a custom function, call something like j = (T)callback(response.DataAsText);
How would you do that in C#?
Update
Here's my JsonState + dependencies declaration:
[System.Serializable]
public class JsonGameDataCell
{
public JsonGameDataBoatCurrentPlayerShot[] c;
public JsonGameDataBoatOpponentShot[] o;
}
[System.Serializable]
public class JsonGameData
{
public JsonGameDataStart start;
public JsonGameDataCell[][] board;
}
[System.Serializable]
public class JsonData
{
public string player;
public JsonGameData game;
}
[System.Serializable]
public class JsonState
{
public int state;
public int state_sub;
public string message;
public JsonData data;
}
And my actual problem is that Unity Json utility can't decode nested arrays, so the property JsonGameDataCell[][] board is always set to null when I call JsonUtility.FromJson(). So I have to implement my own Json decoder. I'll use SimpleJSON which works very well, but I just want to use thise decoder only in that specific case.
Seems to me that you're seeking something called an interface. You can use them to mark some objects so that the application "knows" how to treat them.
You can create such interface as such :
public interface ICustomJson
{
void FromJson(string jsonString);
}
Now in your ConvertAndCallbackyou can just check if(typeof(T).GetInterfaces().Any(i => i == typeof(ICustomJson)))
If it does you can just create an instance of that class casted to ICustomJson and call FromJson(string) method.
Remember that your object can have no default ( parameterless ) constructor so you can create an uninitialized version of that class.
example ConvertAndCallback:
T result = null;
if(typeof(T).GetInterfaces().Any(i => i == typeof(ICustomJson)))
{
result = (T)FormatterServices.GetUninitializedObject(typeof(T));
((ICustomJson)result).FromJson(string);
}
else
{
result = (T)JsonUtility.FromJson<T>(response.DataAsText);
}
Another solution would be ( again ) to use an interface but only for deserializer part. This will involve another class ( or a factory ) to produce a deserializer for the specified type.
You can create an interface called IJsonSerializer with two methods inside T Deserialize(string) and string Serialize(T):
public interface IJsonSerializer<T>
{
T Deserialize(string jsonString);
string Serialize(T jsonObject);
}
Now having this interface, create a class which will implement this
public class JsonStateSerializer : IJsonSerializer<JsonState>
{
public JsonState Deserialize(string jsonString)
{
// put your deserialization code up in here
}
public string Serialize(JsonState jsonObject)
{
// put your serialization code up in here
}
}
Now create the default one:
public class DefaultJsonSerializer<T> : IJsonSerializer<T>
{
public T Deserialize(string jsonString)
{
return (T)JsonUtility.FromJson<T>(jsonString);
}
public string Serialize(T jsonObject)
{
return JsonUtility.ToJson(jsonObject);
}
}
Having these two would be easier to distinguish which one to use later in your ConvertAndCallback method.
Now if you want you can create some Attributes to mark which serializer will be applied to which object or use some factory for that.
I will go with the easiest method and just modify ConvertAndCallback method so that it will have another ( optional ) parameter.
void ConvertThenCallback(HTTPResponse response, bool isGet, IJsonSerializer<T> serializer = null)
{
try
{
if(serializer == null)
{
serializer = new DefaultJsonSerializer<T>();
}
j = serializer.Deserialize(response.DataAsText);
}
catch (ArgumentException)
{
/* Conversion problem */
return;
}
}
And apply this to your Get method too ( so that the serializer would be passed from public to private methods ):
public void Get(string Url, CallbackAjaxFinished cbAjaxFinished, IJsonSerializer<T> serializer = null)
{
// whenever you call ConvertAndCallback
ConvertAndCallback(param1, param2, serializer); // just pass the same serializer here
}
You can now use it with any kind of serializer that implements IJsonSerializer<T> interface or with the default one if none specified.
example usage:
Ajax<JsonState> a = new Ajax<JsonState>();
a.Get(
baseURL + _urlGetState, /* get Url */
/* callback Ajax finished: */
(JsonState j) => { /* do stuff in the callback */ },
new JsonStateSerializer()
);
// or if you want to use default one
Ajax<JsonState> a = new Ajax<JsonState>();
a.Get(
baseURL + _urlGetState, /* get Url */
/* callback Ajax finished: */
(JsonState j) => { /* do stuff in the callback */ }
);
I don't quite understand what you meant but will answer the part I do. Please clarify in the comment if that's what you wanted or if there's something unclear in my answer.

How to ignore a test in C# when CurrentEnv is Prod

have created a ProdIgnoreAttribute which extends from IgnoreAttribute. And I have assigned this attribute to certain tests which I want to run in DEV/QA but not in PROD.
ApplyToTest(Test test) method is not being called in this case. How to resolve this?
public class ProdIgnoreAttribute : IgnoreAttribute
{
private string IgnoreReason { get; }
public ProdIgnoreAttribute(string reason) : base(reason)
{
IgnoreReason = reason;
}
public new void ApplyToTest(Test test)
{
if (test.RunState == RunState.NotRunnable)
return;
if (StaticInfoHelper.VrCurrentEnv == (int)RunEnv.PROD)
{
test.RunState = RunState.Ignored;
test.Properties.Set("_SKIPREASON", (object)IgnoreReason);
}
else
{
base.ApplyToTest(test);
}
}
}
How about extending Attribute rather than IgnoreAttribute?
public class ProdIgnoreAttribute : Attribute, ITestAction
{
public void BeforeTest(TestDetails details)
{
bool ignore = StaticInfoHelper.VrCurrentEnv == (int)RunEnv.PROD;
if (ignore)
Assert.Ignore("Test ignored during Prod runs");
}
//stub out rest of interface
}
If you want a custom ignore message you could make a ProdIgnoreAttribute constructor that accepts a string. You'd then use the attribute on tests like: [ProdIgnore("ignored because xyz")]

Unit Testing of a static factory method containing logic

before I begin with my question I want to point out that I am aware that there are tons of similar questions on stack overflow. Unfortunately none of these questions helped me finding a good solution in my concrete scenario.
The Problem:
I want to write a unit test for a static factory method which contains logic. I am looking for a way to unit test this method even if it is static. If that is not possible maybe someone can point out a better design for my class under test. I also considered using IoC but couldn't see the advantage considering unit-testing.
The Code:
public class Db
{
private XmlMapping mapping;
public static Db<T> Create()
{
var mapping = XmlMapping.Create(typeOf(T).Name);
return new Db(mapping);
}
private Db(XmlMapping mapping)
{
this.mapping = mapping;
}
}
public class XmlMapping //class under test
{
public static XmlMapping Create(string filename) //method under test
{
try
{
ValidateFilename(filename);
//deserialize xml to object of type XmlMapping
var result = Deserialize(filename);
if (result.IsInValid())
throw Exception()
return result;
}
catch (Exception)
{
throw new DbException();
}
}
}
The method Create which I want to unit test is within the class XmlMapping. This method serializes a xml file and generates an object of type XmlMapping. I tried to write a stub for the serialization part. But didn't want to call my Database Factory with a Mapping class in the constructor (constructor injection).
Edit:
My database factory is generic. The generic type is used to figure out which xml file should be louded i.e.: typeOf(T) = Customer --> XmlMapping-File = Customer.xml
The Solution (Thx to Jeff!):
public class XmlMapping : IMapping //class under test
{
internal static Func<Type, IMapping> DeserializeHandler { get; set; }
static XmlMapping()
{
DeserializeHandler = DeserializeMappingFor;
}
public static IMapping Create(Type type)
{
try
{
var mapping = DeserializeHandler(type);
if (!mapping.IsValid())
throw new InvalidMappingException();
return mapping;
}
catch (Exception ex)
{
throw new DataException("Failed to load mapping configuration from xml file.", ex);
}
}
internal XmlMapping(IMapping mapping)
{
this.Query = mapping.Query;
this.Table = mapping.Table;
this.Entity = mapping.Entity;
this.PropertyFieldCollection = mapping.PropertyFieldCollection;
}
private XmlMapping() { }
}
[TestClass]
public class MappingTests //testing class
{
[TestMethod]
public void Create_ValidDeserialization_ReturnsObjectInstance()
{
XmlMapping.DeserializeHandler = MakeFakeHandlerFor(MakeMappingStub());
var result = XmlMapping.Create(typeof(ActivityDto));
Assert.IsInstanceOfType(result, typeof(XmlMapping));
}
}
I would use a fake action handler to assist in verifying the content of the call to deserialize. Let's add a Func delegate property and default that to your serialize method. Your XmlMapping class and test would like something like:
public class XmlMapping //class under test
{
static XmlMapping()
{
// Default the handler to the normal call to Deserialize
DeserializeHandler = Deserialize;
}
public static XmlMapping Create(string filename) //method under test
{
//deserialize xml to object of type XmlMapping
//preudocode:
var result = DeserializeHandler(string.Format("{0}.xml",filename));
//...
return result;
}
// Abstract indirection function to allow you to swap out Deserialize implementations
internal static Func<string, XmlMapping> DeserializeHandler { get; set; }
private static XmlMapping Deserialize(string fileName)
{
return new XmlMapping();
}
}
public class CreateTests {
public void CallingDeserializeProperly()
{
// Arrange
var called = false;
Func<string, XmlMapping> fakeHandler = (string f) =>
{
called = true; // do your test of the input and put your result here
return new XmlMapping();
};
// Act
XmlMapping.DeserializeHandler = fakeHandler;
var m = XmlMapping.Create("test");
// Assert
Assert.IsTrue(called);
}
}

Categories