How does the Value property of TOptions work for IOptions in Core? - asp.net-core-2.0

I am using the Interface IOptions in Core 2.0:
public interface IOptions<out TOptions> where TOptions : class, new()
And in my Startup.cs I can wire it up,
// Example #1: Basic options
// Register the ConfigurationBuilder instance which MyOptions binds against.
services.Configure<MyOptions>(Configuration);
private readonly MyOptions _options;
_options = optionsAccessor.Value;
What I want to know is how does the Framework know what Value is supposed to be? Where is "Value" assigned? It's not the same as value in a property, it appears. Here Value is a whole class reference.

For checking the depth implementation of Options, you could download Options, and debug the project.
how does the Framework know what Value is supposed to be?
While you configure the Options, you have passed the type by services.Configure<MyOptions>(Configuration) , the MyOptions will passed into generic type TOptions.
It's not the same as value in a property, it appears. Here Value is a whole class reference.
Tha Value is TOptions type which is returned by OptionsManager.
public TOptions Value
{
get
{
return Get(Options.DefaultName);
}
}
Where is "Value" assigned?
Value will be configured by ConfigureNamedOptions and created by OptionsFactory, then you could access it by OptionsManager.

Related

How to hardcode the entity varchar value?

The requirement is to store the hardcoded value for varchar which is in an entity file(.eti). I tried adding to the default option but it is not reflecting.
Default option works well with boolean values (true/false), typelists (you can choose a default typecode), monetary amounts too, but it looks like it is not allowed to specify a default varchar.
Therefore the easiest way would be to create a preupdate rule which inserts that default value every time when you create a new record in the database.
Preupdate rule example:
#gw.rules.RuleName("YourEntityAssignDefaultValue")
internal class YourEntityAssignDefaultValueRule {
static function doCondition(yourEntity : entity.YourEntity) : boolean {
return yourEntity.New
}
static function doAction(yourEntity : entity.YourEntity, actions : gw.rules.Action) {
yourEntity.yourColumn = "defaultValue"
}
}
you can achieve through getter and setter properties in an appropriate enhancement class.
public property get PolicyNumber(): String {
return this.PolicyNumber }
and somewhere class you must be assigned the value to the PolicyNumber field then it will reflect.

class properties are not available in generic method c#

I am calling a generic method with two different classes as below:
FillDataPointsInOrder<Metrics>(dataPoints.Where(O => O.SortOrder != null).OrderBy(O => O.SortOrder));
FillDataPointsInOrder<Metric>(angieStatsCmp.GetDataColumns());
private void FillDataPointsInOrder<T>(IEnumerable<T> dataPoints)
{
foreach (T dpoint in dataPoints)
{
if (!dpoint.IsPhone)
FillDrp(this.EmailDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
if (dpoint.IsPhone && this.IsPhoneShop)
FillDrp(this.PhoneDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
}
}
in "FillDataPointsInOrder" method I am getting compile errors :
'T' does not contain a definition for 'IsPhone' and no extension method 'IsPhone' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)
Same errors for Name , MetricId and VName properties.
Not sure why T is not able to access properties of Metrics and Metric.
If I remove the code from generic method and write it directly in foreach over dataPoints it is working fine.
Can somebody advise what is wrong here?
FillDataPointsInOrder only knows it will be called with a T. T could actually be string, int or anything.
If you want to call properties on T, you will have to use a where constraint.
But in this case it looks like your method does not even need to be generic.
If both Metric and Metrics share a base class or an interface that has the properties you need:
interface IMetric {
bool IsPhone {get; }
}
you could just have:
private void FillDataPointsInOrder(IEnumerable<IMetric> dataPoints)
Note that IEnumerable is covariant, so if Metric is a IMetric, IENumerable<Metric> is a IEnumerable<IMetric>
You need to at least tell the compiler something about T if you want to do that. Do you have an interface that has members like IsPhone, Name, MetricId, etc. that your classes implement?
If so you can add a 'where' constraint to your class definition:
public class Something<T> where T : ISomethingElse
...where ISomethingElse is the interface that implements IsPhone.

Dynamically referencing a Service using Felix annotations

I have created an interface which two different services are implementing.
Consider interface is named as CheckReference and two different classes CheckReferenceImpl1 and CheckReferencImpl2 are implementing it.
#Component
#Service(value = CheckReference.class)
#Property(name = "domain", value = "ref1")
public class CheckReferenceImpl1 implements CheckReference
And another one,
#Component
#Service(value = CheckReference.class)
#Property(name = "domain", value = "ref2")
public class CheckReferenceImpl2 implements CheckReference
Now I want to dynamically load the implementation depending on my need using #Reference annotation dynamically.
So , In a check condition
public class LoadReference {
#Reference
CheckReference checkReference
if(check) {
// load checkReferencImpl1
} else {
// load checkReferenceImpl2
}
}
Also I know that I can use target property to load specific implemenation. But that is static way.
But in order to do this dynamically , Not able to relate from specifications and tutorials how should I do this ??
First, you have to make LoadReference a #Component, so that it is managed by the SCR (otherwise #Reference won't work either). Next, you have to provide a configuration for it using the Configuration Admin Service. In this configuration, you can provide a filter for the reference by providing a property with the name REFERENCE_NAME.target:
checkReference.target = FILTER_EXPRESSION
FILTER_EXPRESSION is a standard LDAP-expression used in OSGi-filters. Due to property propagation, this configuration property will be propagated to the service-component, and it will be used when selecting a target service for checkReference. This does not require any code for checking the condition in LoadReference.
Have you looked at ComponentContext.locateService?

EF 5 Re-Use entity configuration

I'm trying to re-use some of the model configurations on several entities that implements a interface.
Check this code:
public static void ConfigureAsAuditable<T>(this EntityTypeConfiguration<T> thisRef)
where T : class, IAuditable
{
thisRef.Property(x => x.CreatedOn)
.HasColumnName("utctimestamp")
.IsRequired();
thisRef.Property(x => x.LastUpdate)
.HasColumnName("utclastchanged")
.IsRequired();
} // ConfigureAsAuditable
as you can see I'm trying to call the extension method "ConfigureAsAuditable" on my onmodelcreating method like this:
EntityTypeConfiguration<Account> conf = null;
conf = modelBuilder.Entity<Account>();
conf.ToTable("dbo.taccount");
conf.ConfigureAsAuditable();
When debugging i get this exception:
The property 'CreatedOn' is not a declared property on type
'Account'. Verify that the property has not been explicitly excluded
from the model by using the Ignore method or NotMappedAttribute data
annotation. Make sure that it is a valid primitive property.
Thanks in advance :)
PD:
I'm using EF 5-rc, VS 2011 and .NET Framework 4.5
I think a better approach would be to implement your own derived version of EntityTypeConfiguration. For example:
public class MyAuditableConfigurationEntityType<T> : EntityTypeConfiguration<T>
where T : class, IAuditable{
public bool IsAuditable{get;set;}
}
Then, when building your model, use that new type:
var accountConfiguration = new MyAuditableConfigurationEntityType<Account>();
accountConfiguration.IsAuditable = true; // or whatever you need to set
accountConfiguration.(HasKey/Ignore/ToTable/Whatever)
modelBuilder.Configurations.Add(accountConfiguration);

Specify RequiredCreationPolicy for non-Attributed Imports

I have an IoC wrapper that uses MEF as it's DI container, an applicable snippet of the wrapper is shown below.
public static bool TryGetComponent<T>(out T component)
{
CompositionContainer container = RetrieveContainer();
T retrievedComponent = container.GetExportedValueOrDefault<T>();
if (retrievedComponent.Equals(default(T)))
{
component = default(T);
return false;
}
component = retrievedComponent;
return true;
}
Most of the exported components in the CompositionContainer specify a CreationPolicy of "Any".
[PartCreationPolicy(CreationPolicy.Any)]
For types that I create I can easily use the following import attribute to get MEF to serve the exported types as NonShared instances.
[Import(RequiredCreationPolicy = CreationPolicy.NonShared)]
However, since my IoC wrapper must also be used by classes that do not use MEF or any of its Import attributes and must use my IoC API to obtain instances exported types. I need a way to specify the CreationPolicy when I programmatically use the CompositionContainer to GetExports and GetExportedValues. Is this even possible without using import attributes?
If you really want to query the container exactly like as if you had a ImportAttribute with RequiredCreationPolicy=NonShared then try creating your own custom ContractBasedImportDefinition. One of the parameters for to the contructor is a CreationPolicy that represents the required creation policy.
Something like:
container.GetExports(new ContractBasedImportDefinition(
AttributedModelServices.GetContractName(type),
AttributedModelServices.GetTypeIdentity(type),
null,
ImportCardinality.ZeroOrMore,
false,
false,
CreationPolicy.NonShared));
Of course you can adjust the parameters as necessary but this will get you moving in the right direction and will cause the container to create NonShared versions of any part that is marked as Any (which is the default).
Well, CreationPolicy is passed as part of a component's metadata. This means, you should be able to query the metadata for the part, and see if it exists. The way CreationPolicy is specified in metadata is to use the full type name System.ComponentModel.Composition.CreationPolicy as the key, and the enum result as the value. So, knowing this we can build an extension method:
public static T GetExportedValueOrDefault<T>(this CompositionContainer container, CreationPolicy creationPolicy)
{
var metadataKey = typeof(CreationPolicy).FullName;
var lazy = container.GetExportedValueOrDefault<T, IDictionary<string, object>>();
if (lazy == null)
return default(T);
if (lazy.Metadata.ContainsKey(metadataKey))
{
// If the creation policy matches the required, return.
if (((CreationPolicy)lazy.Metadata[metadataKey]) == creationPolicy)
return lazy.Value;
}
else
{
// Return the value as we assume it satisfies the default CreationPolicy = Any
return lazy.Value;
}
return default(T);
}
Now, firstly we create our expected key, and then we grab a Lazy<T, TMetadata> instance which includes the type and any associated metadata as a Lazy<T, IDictionary<string, object>> instance. If the lazy comes back as null, we can fail early because there were no matching parts at all.
Next, we can check the metadata dictionary Lazy.Metadata to determine if the metadata exists. If it does, we need to cast and compare against our chosen metadata. If that succeeds, return our part instance.
If that doesn't succeed (e.g., if the part is using the implicit CreationPolicy of Any [i.e., the PartCreationPolicyAttribute is omitted from the export]), we'll assume that the part can be returned, as we can match on the default Any creation policy, so we can match both NonShared and Shared parts.
You should be able to use this in place of the normal GetExportedValueOrDefault<T> call:
T retrievedComponent = container.GetExportedValueOrDefault<T>(CreationPolicy.NonShared);

Resources