Skip to content

Conversation

tsimbalar
Copy link
Member

@tsimbalar tsimbalar commented Nov 17, 2017

as a value for parameters, using the syntax NameSpace.To.ConcreteType::StaticProperty, AssemblyName

What issue does this PR address?
resolves #1057

Does this PR introduce a breaking change?
It shouldn't, although technically, there is a chance that "string" settings whose value looks like "Namespace.To.TypeName::PropertyName" may now be interpreted as a reference to a static property, even though I've done my best to avoid ambiguities.

Please check if the PR fulfills these requirements

  • The commit follows our guidelines
  • Unit Tests for the changes have been added (for bug fixes / features)

Other information:
When / if accepted, similar code should be needed in Serilog.Settings.Configuration to handle issue serilog/serilog-settings-configuration#73 .

as a value for parameters, using the syntax `NameSpace.To.ConcreteType::StaticProperty, AssemblyName`
Copy link
Member

@nblumhardt nblumhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the slow response; this one's looking good to me, just one thought.

@@ -29,6 +35,22 @@ class SettingValueConversions

public static object ConvertToType(string value, Type toType)
{
if (TryParseStaticMemberAccessor(value, out var accessorTypeName, out var memberName))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this could move down to the if ((toTypeInfo.IsInterface || toTypeInfo.IsAbstract) && !string.IsNullOrWhiteSpace(value)) block? If it's first up, here, we might hit issues where this is ambiguous, e.g. the target Type is string.

Copy link
Member Author

@tsimbalar tsimbalar Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my initial implementation, but then I thought it would be strange to limit it to only abstract classes and interfaces, because after all this can also be useful in other cases, like for sinks that accept complex parameters that are not abstract nor interface (for instance : EmailConnectionInfo in Serilog.Sinks.Email , ColumnOptions for Serilog.Sinks.MSSqlServer ...)

This also gives a workaround for configuration that cannot be easily defined with the key-value settings syntax, by allowing to define it as code in a static property.

Also, I've tried to make the regex for static-property accessor as specific as possible to avoid false positives.

What do you think ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nblumhardt any opinion on the subject? :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a fair consideration - just not sure if it's behavior we want to commit to yet in this PR. (We'd also then need to consider whether assembly-qualified type names should be supported in more places, since subclassing is a possible workaround for other scenarios, plus look at how this would interact with some kind of "structure" syntax for populating fields of complex configuration parameters down the track).

TL;DR: I don't think it's a bad idea - just might be scope creep for this PR, since we haven't really dug through all the possible implications :-) .. what do you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense 👍
Easier to make it support a few use cases initially and extend it later on if needed.

Thanks !

Copy link
Contributor

@skomis-mm skomis-mm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great 👍 just a few thoughts

@@ -29,6 +35,22 @@ class SettingValueConversions

public static object ConvertToType(string value, Type toType)
{
if (TryParseStaticMemberAccessor(value, out var accessorTypeName, out var memberName))
{
var accessorType = Type.GetType(accessorTypeName, throwOnError: true);
Copy link
Contributor

@skomis-mm skomis-mm Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, for a better UX could we also use full type names without specifying assembly? We could look for the target type in configuration assemblies (using section) something like:

var accessorType = Type.GetType(typeName) ??
            _assemblies.SelectMany(a => a.ExportedTypes)
                        .FirstOrDefault(t => t.FullName == typeName);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do that for members, could/should we do the same thing for instances?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I've tried to not deviate too much from the way arbitrary sub-types (for interfaces and abstract classes) are referenced, that is with full assembly-qualified type names. Maybe lifting that restriction would be nice, but I would keep it as a separate issue / PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

{
var accessorType = Type.GetType(accessorTypeName, throwOnError: true);
var publicStaticPropertyInfo = accessorType.GetTypeInfo().DeclaredProperties
.Where(x => x.Name == memberName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could also add support for the public static fields at the same time?

Copy link
Member Author

@tsimbalar tsimbalar Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have mixed feelings about accessing arbitrary fields, but I guess if they are public, they are part of the public API so technically accessible. I'll include public fields as well. 👍

@tsimbalar
Copy link
Member Author

I've updated my PR with the suggested changes.

@skomis-mm
Copy link
Contributor

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

KeyValuePairSettings : support for static members via ::
3 participants