镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

ConfigurationBinder fails to bind class that implements IDictionary #77246

Closed

Description

@svkuhn

Description

Binding a Configuration to a class that implements IDictionary<string,T> always results in an empty Dictionary.
The set function throws a System.Reflection.TargetException. I think the problem is that the setter is reflected by Dictionary and not the actual type.

Reproduction Steps

Small test class:

	public class TestDictionaryBinding
	{
		public class CustomDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TKey : notnull
		{

		}

		public class IDictionaryImplementationClass<TKey, TValue> : IDictionary<TKey, TValue> where TKey : notnull
		{
			private Dictionary<TKey, TValue> m_dict = new();

			public TValue this[TKey key] { get => m_dict[key]; set => m_dict[key] = value; }

			public ICollection<TKey> Keys => m_dict.Keys;

			public ICollection<TValue> Values => m_dict.Values;

			public int Count => m_dict.Count;

			public bool IsReadOnly => false;

			public void Add(TKey key, TValue value) => m_dict.Add(key, value);

			public void Add(KeyValuePair<TKey, TValue> item) => m_dict.Add(item.Key, item.Value);

			public void Clear() => m_dict.Clear();

			public bool Contains(KeyValuePair<TKey, TValue> item) => m_dict.Contains(item);

			public bool ContainsKey(TKey key) => m_dict.ContainsKey(key);

			public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => throw new NotImplementedException();

			public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => m_dict.GetEnumerator();

			public bool Remove(TKey key) => m_dict.Remove(key);

			public bool Remove(KeyValuePair<TKey, TValue> item) => m_dict.Remove(item.Key);
			
			public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) => m_dict.TryGetValue(key, out value);

			IEnumerator IEnumerable.GetEnumerator() => m_dict.GetEnumerator();
		}

		[Fact]
		public void Test_InterfaceDictionary()
		{
			var _cfg = new Dictionary<string, string>()
			{
				{ "key", "value" }
			};

			var _config = new ConfigurationBuilder()
				.AddInMemoryCollection(_cfg!)
				.Build();

			var _dictionary = _config.Get<Dictionary<string, string>>(); // success
			var _dictionaryInterface = _config.Get<IDictionary<string, string>>(); // success
			var _customDictionaryClass = _config.Get<CustomDictionary<string, string>>(); // success
			var _customIDictionaryImplementation = _config.Get<IDictionaryImplementationClass<string, string>>(); // empty

			Assert.Single(_dictionary);
			Assert.Single(_dictionaryInterface);
			Assert.Single(_customDictionaryClass);
			Assert.Single(_customIDictionaryImplementation);
		}
	}

Expected behavior

Items from Configuration should be added to a IDictionary implementation

Actual behavior

Custom IDictionary implementation is empty

Regression?

Was working in
7.0.0-preview.7.22375.6

Known Workarounds

No response

Configuration

Used packages for Test:

Other information

No response

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Oct 20, 2022
  2. eerhardt commented on Oct 20, 2022

    @eerhardt
    Member

    fyi @SteveDunn - this looks like another regression from #68133

  3. added this to the 8.0.0 milestone on Oct 20, 2022
  4. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on Oct 20, 2022
  5. ghost added
    in-prThere is an active PR which will close this issue when it is merged
    on Oct 28, 2022
  6. ghost removed
    in-prThere is an active PR which will close this issue when it is merged
    on Oct 30, 2022
  7. tarekgh commented on Nov 11, 2022

    @tarekgh
    Member

    This fix will be included in the next 7.0 servicing release. #78118

  8. ghost locked as resolved and limited conversation to collaborators on Dec 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions