"CreatePropertyValue" returns null when attribute inherits from ITypeDestructuringAttribute
aholeton opened this issue · 3 comments
I was attempting to create a custom attribute that needs to inspect multiple properties on an object to determine whether or not a specific property should be masked. When using propertyValueFactory.CreatePropertyValue(value, true);
it looks like it is returning null as opposed to an object.
If this is not the right way to go about this, then any help would be appreciated on what I should be doing instead.
Describe the bug
When creating a custom attribute inheriting from ITypeDestructuringAttribute
, the method propertyValueFactory.CreatePropertyValue(value, true)
, always returns null
.
Expected behavior
Something other than null.
Screenshots and any additional context
[AttributeUsage(AttributeTargets.Class)]
public class LogSensitiveDataAttribute : Attribute, ITypeDestructuringAttribute
{
public LogEventPropertyValue CreateLogEventPropertyValue(object? value, ILogEventPropertyValueFactory propertyValueFactory)
{
// this always returns null
var result = propertyValueFactory.CreatePropertyValue(value, true);
// other code
}
}
You get into recursive trap with aforementioned code. Look:
Eventually you end in that method in Serilog core project:
You may enable SelfLog
to verify that.
Code to reproduce:
using Destructurama.Attributed.Tests.Support;
using NUnit.Framework;
using Serilog.Core;
using Serilog.Events;
using Shouldly;
namespace Destructurama.Attributed.Tests;
// https://github.com/destructurama/attributed/issues/111
[TestFixture]
public class Issue111
{
[Test]
public void Issue_111()
{
var customized = new MyClass();
var evt = DelegatingSink.Execute(customized);
evt.Properties["Customized"].ShouldBe(ScalarValue.Null);
}
[LogSensitiveData]
public class MyClass
{
public string Foo { get; set; } = "Foo123";
public string Bar { get; set; } = "Bar123";
}
[AttributeUsage(AttributeTargets.Class)]
public class LogSensitiveDataAttribute : Attribute, ITypeDestructuringAttribute
{
public LogEventPropertyValue CreateLogEventPropertyValue(object? value, ILogEventPropertyValueFactory propertyValueFactory)
{
// this always returns null
var result = propertyValueFactory.CreatePropertyValue(value, true);
return result;
}
}
}
Thanks for taking the time to look at this. I need to inspect multiple properties to determine if a specific property should be masked. Given your example, is it possible to inspect property Foo
to determine whether property Bar
should be masked?
You can do this via reflection or by any other mean but not by calling CreatePropertyValue
passing the value
itself which in turn calls into LogSensitiveDataAttribute
again.