For example: I have a custom attribute class similar to the following:
[System.AttributeUsage(System.AttributeTargets.Method)
]
public class Yeah: System.Attribute
{
public double whatever = 0.0;
}
Now I decorate some method with it like that:
[Yeah(whatever = 2.0)]
void SampleMethod
{
// implementation
}
Is it possible to access the Yeah-attribute through injecting the code via aspects? I would prefer the postsharp framework for AOP but I am also happy with any other solution because I think that there is such a feature in postsharp but only available in the professional edition (mentioned here: PostSharp Blog)
Take a look on NConcern .NET AOP Framework. This is a new open source project on which I actively work.
//define aspect to log method call
public class Logging : IAspect
{
//define method name console log with additional whatever information if defined.
public IEnumerable<IAdvice> Advise(MethodInfo method)
{
//get year attribute
var year = method.GetCustomAttributes(typeof(YearAttribute)).Cast<YearAttribute>().FirstOrDefault();
if (year == null)
{
yield return Advice.Basic.After(() => Console.WriteLine(methode.Name));
}
else //Year attribute is defined, we can add whatever information to log.
{
var whatever = year.whatever;
yield return Advice.Basic.After(() => Console.WriteLine("{0}/whatever={1}", method.Name, whatever));
}
}
}
public class A
{
[Year(whatever = 2.0)]
public void SampleMethod()
{
}
}
//Attach logging to A class.
Aspect.Weave<Logging>(method => method.ReflectedType == typeof(A));
//Call sample method
new A().SampleMethod();
//console : SampleMethod/whatever=2.0
My logging aspect simply write method name when method called. it include whatever information when it is defined.
Related
I have a interface where I am returning result for a check and this interface has currently 2 implantations but in future it will keeps added.
public interface ICheck
{
Task<CheckReturn> GetCheckReturn(string fileName);
}
public class ATypeCheck : ICheck
{
public async Task<CheckReturn> GetCheckReturn(string fileName)
{
//logic to check A Type
//return CheckReturn with right content type
return await Task.FromResult<CheckReturn>(new CheckReturn { ContentType = "Type A" });
}
}
public class BTypeCheck : ICheck
{
public async Task<CheckReturn> GetCheckReturn(string fileName)
{
//logic to check A Type
//return CheckReturn with right content type
return await Task.FromResult<CheckReturn>(new CheckReturn { ContentType = "Type B" });
}
}
// Future CTypeCheck
// Future DTypeCheck
With below code I am able to do only one check validation, but I need to check all the implementation of ICheck?
static async Task Main(string[] args)
{
ATypeCheck check = new ATypeCheck();
var result = await check.GetCheckReturn("XYZ");
}
Which design pattern help here & how?
2 Parts to a solution:
Part 1: Code against interfaces
static async Task Main(string[] args)
{
ICheck checks = new List<ICheck>{ new ATypeCheck(), new BTypeCheck() };
var results = new List<CheckResult>();
foreach( var check in checks ) results.Add(await check.GetCheckReturn("XYZ"));
// TODO handle results
}
Part 2: Dependency Injection
In production code, you probably will want to detect all implementations of the interface at startup and inject your clients with that list of interface-implementations.
You can do that using reflection.
There are questions regarding this already, so I would consider this part a duplicate. You can refer to for example this question.
The reason I recommend doing this via DI and not just at runtime is that reflection might be slow and you would want that done once at startup and that's it. But you are not locked in to DI.
You could of course as well just construct the list of implementations like in the example of Part 1. But that would mean you'd have to keep track of new implementations and add them there (which is bad and will lead to "forgotten" impls sooner or later).
If you're using DI you could register various implementations and then inject them as IEnumerable<YourInterface>
eg.
public class SomeConsumer() {
private readonly IEnumerable<IYourInterface> _allServices;
public SomeConsumer(IEnumerable<IYourInterface> allServices) {
_allServices = allServices;
// ...
}
// use _allServices in code to get all implementations
}
To register various implementations use standard AddScoped, AddTransient etc. methods.
// Program.cs
// ...
builder.Services.AddScoped<IYourInterface, Implementation1>();
builder.Services.AddScoped<IYourInterface, Implementation2>();
//...
I would like to change this:
var context = GlobalHost.ConnectionManager.GetHubContext<ControlHub>();
context.Clients.All.sentMessage(room, username, message);
to something like this using a variable as part of the call;
var variableHere = "<ControlHub>";
var context = GlobalHost.ConnectionManager.GetHubContext(variableHere)();
context.Clients.All.sentMessage(room, username, message);
I'm having trouble getting this pulled together. I' m thinking reflection or delegate work flow will get me there but have floundered in getting either approach to work.
I am trying to figure out how to insert a variable as part of a method/function call. In C# (specifically a MVC framework)
Any advise or assistance is appreciated.
You don't need reflection here. There is another overload for ConnectionManager.GetHubContext which accepts the hub name as parameter.
You can your code you use the other overload like this:
string hubName = "the hub name";
var context = GlobalHost.ConnectionManager.GetHubContext(hubName);
Just in case you want to extract the hub name based on the type, take a look at how it's being done internally in SignalR source code. If you need a similar functionality, change the below GetHubName extension methods to public extension methods and use it:
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.SignalR.Hubs
{
internal static class HubTypeExtensions
{
internal static string GetHubName(this Type type)
{
if (!typeof(IHub).IsAssignableFrom(type))
{
return null;
}
return GetHubAttributeName(type) ?? GetHubTypeName(type);
}
internal static string GetHubAttributeName(this Type type)
{
if (!typeof(IHub).IsAssignableFrom(type))
{
return null;
}
// We can still return null if there is no attribute name
return ReflectionHelper
.GetAttributeValue<HubNameAttribute, string>(type, attr => attr.HubName);
}
private static string GetHubTypeName(Type type)
{
var lastIndexOfBacktick = type.Name.LastIndexOf('`');
if (lastIndexOfBacktick == -1)
{
return type.Name;
}
else
{
return type.Name.Substring(0, lastIndexOfBacktick);
}
}
}
}
I have a custom tag defined in my Hook.cs file like
[BeforeScenario("AfterUpgradeTag")]
public void BeforeScenarioAfterUpgrade()
{
// Code execution here
}
What I want to do is I want to change its method definition like
[BeforeScenario("AfterUpgradeTag")]
public void BeforeScenarioAfterUpgrade(bool flag)
{
if(flag)
// Code execution here
else
//Do a clean up
}
And I want to use this in feature file as something like
#AfterUpgradeTag(bool val = false)
I have searched alot for this. I want to know is this possible using Specflow or if there are any alternatives
I am not sure if you can pass parameters like that in feature file but you can utilize tags to achieve your goal
In feature file do this
#upgrade #false
Scenario: testing upgrade
In binding class
public static ScenarioContext _scenarioContext;
and binding class constructor
public BindingClass(ScenarioContext scenarioContext)
{
_scenarioContext = scenarioContext;
}
and your BeforeScenario method is defined like this in the class BindingClass
[BeforeScenario("upgrade")]
public void BeforeScenarioUpgradeFalseorTrue()
{
if (BindingClass._scenarioContext.ScenarioInfo.Tags.Contains("false"))
{
log.Info("upgrade is false..");
}
if (BindingClass._scenarioContext.ScenarioInfo.Tags.Contains("true"))
{
log.Info("upgrade is true..");
}
}
when you want to pass true in feature file just do
#upgrade #true
Scenario: testing upgrade
You can follow the documentation from specflow to achieve this.
Hi i am new to DI with unity. I am developing a custom Attribute. In that attribute I want to inject a dependency with help of Unity. But when use of that attribute in a class it shows exception. The code is:
public interface ITest
{
}
public class AAttrib : Attribute
{
ITest _test;
public AAttrib(ITest test)
{
_test = test;
}
}
public class Test : ITest
{
}
[AAttrib]
public class Example
{
// to do
}
the exception is:
There is no argument given that corresponds to the required formal
parameter 'test' of 'AAttrib.AAttrib(ITest)
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITest, Test>(new HierarchicalLifetimeManager());
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
the Unity resolver class is:
public class UnityResolver: IDependencyResolver
{
protected IUnityContainer _container;
public UnityResolver(IUnityContainer container)
{
if(container == null)
throw new ArgumentNullException("container");
this._container = container;
}
public void Dispose()
{
_container.Dispose();
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException r)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new UnityResolver(child);
}
}
You cannot use Dependency Injection on Attributes, cause Attributes are Metainformation that extend the meta information of classes. And these meta information are generated during compile time
It is indeed not possible to use DI in attributes. There is however a nice clean workaround by using a decorator.
See this blog: https://blogs.cuttingedge.it/steven/posts/2014/dependency-injection-in-attributes-dont-do-it/
I tried this and I've been using it for quite some time now. You will be able to do exactly what you need with this.
(Blog has .net framework & .net core solutions)
Apologies for late entry.
Not sure if unity can let you do that. But PostSharp has a way of achieving this. I've never tried this as PostSharp wasn't an approved DI framework in my project. But I liked the solution.
Auto data contract
This doesn't answer your question but gives a different perspective to the solution that you are thinking.
You should avoid attributes. Attributes are good starting point but get in the way of application extension.
Attributes are hardcoding and is violation of at least two SOLID principles, Single Responsibility and Open/Closed principles. It should rather be done using Fluent APIs
I would rather replace AAttrib with a Fluent API.
Attribute Example
public class Person {
[StringLength(100)]
[RegularExpression("^([a-zA-Z0-9 .&'-]+)$", ErrorMessage = "Invalid First Name")]
public string FirstName { get; set; }
}
FluentValidation Example:
public class Person {
public string FirstName { get; set; }
}
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.FirstName).NotNull().WithMessage("Can't be null");
RuleFor(x => x.FirstName).Length(1, 100).WithMessage("Too short or long");
RuleFor(x => x.FirstName).Matches("^([a-zA-Z0-9 .&'-]+)$").WithMessage("Invalid First Name"));
}
}
This will essentially do the same thing that attribute is doing. With the right DI wiring in place. This can introduce great flexibility. Read other articles on wiring attributes with members.
I want to create a simple Ninject provider that returns Moq'd instances instead of concrete types. So far I have this:
public class NinjectMockProvider<T> : IProvider
{
public static Type Type { get { return typeof(T); } }
public object Create(IContext context)
{
Mock<T> newMock = new Mock<T>();
return newMock.Object;
}
}
But this is all wrong I'm sure as I don't know what I'm doing really. Any help and code samples would be great. I just want the ability to do:
kernel.Bind<ISomeInterface>().ToProvider<NinjectMoqProvider<ISomeInterface>>();
or something to that effect.
Update
I did figure out that I could accomplish what I want by using Ninject's method binding:
kernel.Bind<ISomeInterface>().ToMethod(x => new Mock<ISomeInterface>().Object);
I still would like a more elegant way and I may have to check out Ninject.Moq as suggested by Ian, but if anyone has any real code examples that would be awesome.
Does the MockingKernel extension handle what you need? It has Moq, RhinoMocks, and NSubstitute flavors, and it is also available on NuGet.
My solution to this always just uses the following:
MoqProvider
public class MoqProvider<T> : Provider<T> // T is the desired service
{
protected override T CreateInstance(IContext context)
{
return new Mock<T>().Object;
}
}
I then also register an IMissingBindingResolver with my kernel. The MoqMissingBindingResolver simply creates a new binding to a MoqProvider for any service for which a binding does not already exist.
MoqMissingBindingResolver
public class MoqMissingBindingResolver : NinjectComponent, IMissingBindingResolver
{
public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, IRequest request)
{
if (request.Service.IsAbstract || request.Service.IsInterface)
{
var moqProvider = (IProvider)Activator.CreateInstance(typeof(MoqProvider<>).MakeGenericType(request.Service));
return new IBinding[]
{
new Binding(request.Service, new BindingConfiguration
{
ProviderCallback = ctx => moqProvider,
ScopeCallback = Settings.DefaultScopeCallback
})
};
}
else
{
return Enumerable.Empty<IBinding>();
}
}
}
I typically also set Settings.DefaultScopeCallback to singleton so that I can request my mocked objects in my tests later on when I need to verify certain calls have or haven't taken place, or setup behaviour on mocks prior to executing the test. So setting up my kernel will look like the following:
INinjectSettings Settings = new NinjectSettings
{
DefaultScopeCallback = StandardScopeCallbacks.Singleton
};
var k = new StandardKernel(Settings);
k.Components.Add<IMissingBindingResolver, MoqMissingBindingResolver>();
Hope this is helpful.