Using Windsor 2.5.2, the following works:
public class Foo
{
public IBar Bar { get; set; }
}
To delay creation of IBar, this also works:
public class Foo
{
public Foo(Func<IBar> barFactory)
{
}
}
However, if I combine property injection with Func<T>, the following results in a null reference:
public class Foo
{
public Func<IBar> Bar { get; set; }
}
How can I make Windsor inject the Func<IBar>?
That's a great question Paul. I'm glad you asked.
For implicitly registered Funcs Windsor is looking at the property, sees it's optional, and it just doesn't bother trying to get it, since... well - it's optional, so you surely are happy not having the dependency populated.
To have it populated, you either register the factory explicitly
container.Register(Component.For<Func<IBar>>().AsFactory().Lifestyle.Transient);
or you mark the dependency as required (on ComponentModel using Require method) which is probably best done via an IComponentModelConstructionContributor
Related
I am attempting to create my first Razor Component in a Blazor Server-side project. The Razor Component is named MyComponent and has a property configured to retrieve its value from input:
MyComponent.razor
[Parameter]
public int Count {get; set;}
I am pulling the count from an injected service configured via IServiceCollection, which looks like this:
public interface ICountingService
{
ValueTask<int> Get();
}
The hosting page, Index.razor looks like the following:
#page "/"
#inject ICountingService Counter
<h1>Hello World!</h1>
<MyComponent Count="#Counter.Get()" />
However, I cannot seem to bind the correct value for the Count property.
I get the following error:
cannot convert from 'System.Threading.Tasks.ValueTask<int>' to 'int'
All of the examples I have found for assigning [Parameter] values to Razor Components are synchronous, and the only asynchronous values I have found are for callbacks and methods (not parameters).
Further, searching online did not return anything obvious so I am posting here in hopes of finding an answer.
Note that I am aware of using protected override async Task OnInitializedAsync and storing a value in there, but that seems like a lot of required ceremony compared to the approach above, especially when considering the multiple services and properties that I will ultimately have to bind.
So, how does one assign values from an asynchronous call to a Razor Component [Parameter] property in the way that I would prefer?
The problem is, Counter.Get() isn't an int value; it's a Task that will have an int at some undefined point either now or in the future. So you can't assign its value to something that's expecting an int right now, because that int doesn't necessarily exist yet.
You've already got the answer, and though it "seems like a lot of ceremony", it's really the only way to do this:
Create an int property to hold the value.
Declare an async method
In that method, assign the awaited value of Counter.Get() to the int that's holding the value
Set the component's Count property equal to the int property
It may feel like a lot of ceremony, but you should be grateful. Asynchrony is inherently very complicated, and having async/await available already takes care of about 95% of the hard work for you. If you think this solution is messy, you oughtta see what it would take to get it right without async/await!
Try this.
#page "/"
#inject ICountingService Counter
<h1>Hello World!</h1>
<MyComponent Count="#CounterValue" />
#code{
public int CounterValue {get; set;}
protected override async Task OnInitializedAsync()
{
CounterValue = await Counter.Get();
}
}
After #mason-wheeler and #rich-bryant provided their answers, I went to think about this a little more and found my solution, which I have posted here:
https://github.com/Mike-E-angelo/Blazor.ViewProperties
I am calling it a ViewProperty which looks like the following:
public interface IViewProperty
{
ValueTask Get();
}
public sealed class ViewProperty<T> : IViewProperty
{
public static implicit operator ViewProperty<T>(ValueTask<T> instance) => new ViewProperty<T>(instance);
readonly ValueTask<T> _source;
public ViewProperty(ValueTask<T> source) => _source = source;
public T Value { get; private set; }
public bool HasValue { get; private set; }
public async ValueTask Get()
{
Value = await _source;
HasValue = true;
}
public override string ToString() => Value.ToString();
}
You then pair it with a component base type that then iterates through the component's view properties and invokes their respective asynchronous operations:
public abstract class ViewPropertyComponentBase : ComponentBase
{
protected override async Task OnParametersSetAsync()
{
var properties = GetType().GetRuntimeProperties();
foreach (var metadata in properties.Where(x => x.GetCustomAttributes<ParameterAttribute>().Any() &&
typeof(IViewProperty).IsAssignableFrom(x.PropertyType)))
{
if (metadata.GetValue(this) is IViewProperty property)
{
await property.Get().ConfigureAwait(false);
}
}
}
}
A sample razor component that uses the above:
MyComponent.razor
#inherits ViewPropertyComponentBase
#if (Count.HasValue)
{
<p>Your magic number is #Count.</p>
}
else
{
<p>Loading, please wait...</p>
}
#code {
[Parameter]
public ViewProperty<int> Count { get; set; }
}
The resulting use is a clean view with direct bindings and no need for overrides or other additional ceremony:
#page "/"
#inject ICounter Count
<h1>Hello, world!</h1>
Welcome to your new app.
<MyComponent Count="#Count.Count()" />
(NOTE that my posted example and above uses reflection, which is slow. In the actual version of the solution that I am using, I compile the member access as lambda expressions and cache the result. You can find that by starting here if you are brave enough to poke around.)
It feels a bit hacky, but you could do something like this:
<MyComponent Count="#Counter.Get().Result" />
I am having an issue while trying the WebAPI of net core.
For some reason my object always comes empty no matter what I try. I've checked several other SO questions regarding this but cannot find a solution for what I am facing.
My model:
My controller (getting the null object):
And the POSTMAN request:
I've tried both with and without the [FromBody] option as I've seen in other SO questions that some people solved their issues with it.
Any ideas?
All the auto-implemented properties must have an public modifier before them to for JSON.NET to safely deserialize them.
public class APIRequest
{
string Action { get; set; }
}
Because in the above example no access modifier is given, thereby making it as private, so the default value of the property is assigned which is default(string) that is null.
public class APIRequest
{
public string Action { get; set; }
}
By default all class members are private and the class itself is internal, so you have to mark your property with public modifier.
I have a ASP.NET MVC4 application and am using Unity for IOC. I am using Unity.MVC4 and UnityConfiguration Nuget packages to help with the registration.
I need to automatically register a load of interfaces and their related types to the Unity container. To do this I created a dummy interface; IDependencyInjectionScanner that all my real interfaces inherit from. Below is the code showing that.
public interface IDependencyInjectionScanner
{
}
public interface IChair : IDependencyInjectionScanner
{
NumberOfLegs { get; set; }
}
public class Chair : IChair
{
public NumberOfLegs { get; set; }
}
public interface ITable : IDependencyInjectionScanner
{
NumberOfChairs { get; set; }
}
public class Table : ITable
{
public NumberOfChairs { get; set; }
}
I then used UnityConfiguration to bind the registrations using the scanner. I have get the interfaces being correctly resolved in the controller. Below is the code that shows how I did the binding.
Scan(scan =>
{
scan.AssembliesInDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"));
scan.With<FirstInterfaceConvention>();
scan.Include(x => (x.GetInterface(typeof(IDependencyInjectionScanner).Name) != null));
scan.ForRegistries();
});
The problem is that I want to register all the types found by the scanner using the hierarchical lifetime manager but can figure out how to do this. The GitHub page for UnityConfiguration https://github.com/thedersen/UnityConfiguration states that this could be achieved by the code below:
Configure<IChair>().AsHierarchicalControlled();
However I if I have to do that for each of the interfaces bound by the scanner then the scanner is of no use as I may as well do:
Register<IChair, Chair>().AsHierarchicalControlled();
Can someone assist me with finding a solution to this please.
Here's an answer to your question using UnityConfiguration. You can create a custom convention to configure the lifetime. Just be careful because it looks like the calls within the Scan() method are order dependent.
public class HierarchicalLifetimeConvention : IAssemblyScannerConvention
{
public void Process(Type type, IUnityRegistry registry)
{
registry.Configure(type).AsHierarchicalControlled();
}
}
and then add that to your Scan() call...
Scan(scan =>
{
scan.AssembliesInDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"));
scan.With<FirstInterfaceConvention>();
scan.With<HierarchicalLifetimeConvention>(); //<-- New convention
scan.Include(x => (x.GetInterface(typeof(IDependencyInjectionScanner).Name) != null));
scan.ForRegistries();
});
As suggested by #TylerOhlsen I used the built-in Registration by Convention feature of Unity 3.0. I have got it to add the registration mappings and they are using the hierarchical lifetime manager. below is the code for that
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().Where(
t => t.GetInterface(typeof(IDependencyInjectionScanner).Name) != null),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.Hierarchical);
There is one thing that is disturbing me; when I look at the registrations I have 4 (based on the example code above). 2 type mappings for the Chair type and 2 type mappings for the Table type.
Can anyone shed any light on why this is, as I was only expecting two mappings.
I want to auto register all interfaces which name ends with "Service" and also doesn't have concrete implementations to be resolved to a generated type/proxy (which off course differs per interface).
So when I want to resolve IContractService I want it to return a proxied object. I got this idea from this article where they implemented it in some way with Castle Windsor.
What would be the structuremap approach for achieving this. I tried all kind of things with custom conventions and all but I can't get my head around it.
I fixed this by using Castle's Dynamic Proxy and a StructureMap convention. BTW. I also renamed some of the classes mentioned in the article.
public class InfraRegistry : Registry
{
public InfraRegistry()
{
For<IClientProviderFactory>().Use<WcfClientProviderProviderFactory>();
Scan(scan =>
{
scan.AssemblyContainingType<MidleWareServiceConvention>();
scan.Convention<MidleWareServiceConvention>();
});
}
}
public class MidleWareServiceConvention : IRegistrationConvention
{
private readonly ProxyGenerator _proxyGen = new ProxyGenerator();
public void Process(Type type, Registry registry)
{
if (type.IsInterface && type.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))
{
registry.For(type)
.HybridHttpOrThreadLocalScoped()
.Use(
context =>
_proxyGen.CreateInterfaceProxyWithoutTarget(type,
new WcfInterceptor(
context.GetInstance<IClientProviderFactory>())));
}
}
}
I have carried the method here on almost all of the areas where I have had overridable methods and managed to fix them but there is one part where the method doesnt work in the same way on a different contexted piece of code:
public Employee()
{
this.InitMembers();
}
private void InitMembers()
{
// Init the collection so it's never null
this.Territories = new List<Territory>();
}
public Employee(string firstName, string lastName): this()
{
this.reffirstName = firstName;
this.reflastName = lastName;
}
> public virtual IList<Territory> Territories { get; protected set; }
Where again the > is the code causing the error, I do however get an intellisense option to "Convert to auto property", which simply reverts the code to when it was started and not fixing the problem.
Anyone know what modifications need to be made to this part to elimiate the fxcop violation?
The error appears because your private constructor is calling a method that can be overridden from a derived class. To fix the warning, you need to remove any calls to virtual methods from within the constructor.
In the example you list, InitMembers uses 'this.Territories', which is causing the violation. According to your later comment you have added a private member - use that instead.