-
-
Save ritalin/2418469 to your computer and use it in GitHub Desktop.
A helper class to extract property-names of ViewModel for MVVM.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
namespace Samples { | |
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] | |
public class PropertyCategoryAttribute : System.Attribute { | |
public PropertyCategoryAttribute(Type inTagType) { | |
this.Tag = inTagType; | |
} | |
public Type Tag { get; internal set; } | |
} | |
public class PropertyCategoryMapper { | |
public static PropertyCategoryMapper Create<TViewModel>() { | |
return new PropertyCategoryMapper(typeof(TViewModel)); | |
} | |
public static PropertyCategoryMapper Create(Type inType) { | |
return new PropertyCategoryMapper(inType); | |
} | |
private Dictionary<Type, string[]> mTagMap; | |
private PropertyCategoryMapper(Type inType) { | |
mTagMap = ( | |
inType.GetTypeInfo().DeclaredProperties | |
.Where(p => p.CanRead) | |
.SelectMany(p => { | |
return p.GetCustomAttributes<PropertyCategoryAttribute>(true).Select(attr => { | |
return new KeyValuePair<Type, string>(attr.Tag, p.Name); | |
}); | |
}) | |
.GroupBy(pair => pair.Key, pair => pair.Value) | |
.ToDictionary(pair => pair.Key, pair => pair.ToArray()) | |
); | |
} | |
public string[] ToProprtyNames(Type inTag) { | |
return ToProprtyNamesCore(inTag); | |
} | |
public string[] ToProprtyNames<TCategoryTag>() { | |
return ToProprtyNamesCore(typeof(TCategoryTag)); | |
} | |
private string[] ToProprtyNamesCore(Type inTag) { | |
string[] props; | |
if (mTagMap.TryGetValue(inTag, out props)) { | |
return props; | |
} | |
else { | |
return new string[0]; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
namespace Samples { | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using NUnit.Framework; | |
using NUnit.Framework.Constraints; | |
namespace Samples { | |
public class _PropertyTagに関するテストスイート { | |
[Test] | |
public void _プロパティ名の収集テスト() { | |
var vm = new PropertyCategoryTestViewModel(); | |
var mapper = PropertyCategoryMapper.Create(vm.GetType()); | |
string[] names; | |
names = mapper.ToProprtyNames<TestTag.Unknown>()); | |
Assert.That(names.Length, Is.EqualTo(0), "TestTag.Unknownは未指定"); | |
names = mapper.ToProprtyNames<TestTag.Numeric>()); | |
Assert.That(names.Length, Is.EqualTo(3), "intとdoubleが対象"); | |
Assert.That(names, Does.Contains("Value1"), "Value1は含む"); | |
Assert.That(names, Does.Contains("Value2"), "Value2は含む"); | |
Assert.That(names, Does.Contains("Num1"), "Num1は含む"); | |
Assert.That(names, Does.Not.Contains("Text1"), "Text1は含まない"); | |
Assert.That(names, Does.Not.Contains("CreatedAt"), "CreatedAtは含まない"); | |
Assert.That(names, Does.Not.Contains("ModifiedAt"), "ModifiedAtは含まない"); | |
names = mapper.ToProprtyNames<TestTag.Strings>()); | |
Assert.That(names.Length, Is.EqualTo(1), "stringが対象"); | |
Assert.That(names, Does.Contains("Text1"), "Text1は含む"); | |
Assert.That(names, Does.Not.Contains("Value1"), "Value1は含まない"); | |
Assert.That(names, Does.Not.Contains("Value2"), "Value2は含まない"); | |
Assert.That(names, Does.Not.Contains("Num1"), "Num1は含まない"); | |
Assert.That(names, Does.Not.Contains("CreatedAt"), "CreatedAtは含まない"); | |
Assert.That(names, Does.Not.Contains("ModifiedAt"), "は含まない"); | |
names = mapper.ToProprtyNames<TestTag.Dates>()); | |
Assert.That(names.Length, Is.EqualTo(2), "DateTimeが対象"); | |
Assert.That(names, Does.Contains("CreatedAt"), "CreatedAtは含む"); | |
Assert.That(names, Does.Contains("ModifiedAt"), "ModifiedAtは含む"); | |
Assert.That(names, Does.Not.Contains("Value1"), "Value1は含まない"); | |
Assert.That(names, Does.Not.Contains("Value2"), "Value2は含まない"); | |
Assert.That(names, Does.Not.Contains("Num1"), "Num1は含まない"); | |
Assert.That(names, Does.Not.Contains("Text1"), "Text1は含まない"); | |
names = mapper.ToProprtyNames<TestTag.Custom1>()); | |
Assert.That(names.Length, Is.EqualTo(2), "CreatedAtとValue2フィールドが対象"); | |
Assert.That(names, Does.Contains("CreatedAt"), "CreatedAtは含む"); | |
Assert.That(names, Does.Contains("Value2"), "Value2は含む"); | |
Assert.That(names, Does.Not.Contains("Value1"), "Value1は含まない"); | |
Assert.That(names, Does.Not.Contains("Num1"), "Num1は含まない"); | |
Assert.That(names, Does.Not.Contains("Text1"), "Text1は含まない"); | |
Assert.That(names, Does.Not.Contains("ModifiedAt"), "ModifiedAtは含まない"); | |
names = mapper.ToProprtyNames<TestTag.Custom2>()); | |
Assert.That(names.Length, Is.EqualTo(3), "CreatedAtとNum1とText1フィールドが対象"); | |
Assert.That(names, Does.Contains("CreatedAt"), "CreatedAtは含む"); | |
Assert.That(names, Does.Contains("Num1"), "Num1は含む"); | |
Assert.That(names, Does.Contains("Text1"), "Text1は含む"); | |
Assert.That(names, Does.Not.Contains("Value1"), "Value1は含まない"); | |
Assert.That(names, Does.Not.Contains("Value2"), "Value2は含まない"); | |
Assert.That(names, Does.Not.Contains("ModifiedAt"), "ModifiedAtは含まない"); | |
} | |
} | |
internal static class Does { | |
public static ConstraintExpression Not { | |
get { | |
return Is.Not; | |
} | |
} | |
public static ContainsConstraint Contains(string expected) { | |
return new ContainsConstraint(expected); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace TestTag { | |
public interface Unknown {} | |
public interface Numeric {} | |
public interface Strings {} | |
public interface Dates {} | |
public interface Custom1 {} | |
public interface Custom2 {} | |
} | |
internal class PropertyCategoryTestViewModel : INotifyPropertyChanged { | |
private PropertyCategoryMapper mMapper; | |
private DateTime mCreatedAt = DateTime.Now; | |
private DateTime mModifiedAt = DateTime.Now; | |
public PropertyCategoryTestViewModel() { | |
mMapper = PropertyCategoryMapper.Create(this.GetType()); | |
} | |
public event PropertyChanged; | |
protected void OnPropertyChanged(string[] inNames) { | |
if (this.PropertyChanged != null) { | |
foreach (var name in inNames) { | |
this.PropertyChanged(name); | |
} | |
} | |
} | |
public void DoHoge() { | |
// Do something ... | |
this.OnPropertyChanged(mMapper.ToProprtyNames<TestTag.Numeric>()); | |
} | |
[PropertyCategory(typeof(TestTag.Numeric))] | |
public int Value1 { get; set; } | |
[PropertyCategory(typeof(TestTag.Numeric))] | |
[PropertyCategory(typeof(TestTag.Custom1))] | |
public int Value2 { get; set; } | |
[PropertyCategory(typeof(TestTag.Numeric))] | |
[PropertyCategory(typeof(TestTag.Custom2))] | |
public double Num1 { get; set; } | |
[PropertyCategory(typeof(TestTag.Strings))] | |
[PropertyCategory(typeof(TestTag.Custom2))] | |
public string Text1 { get; set; } | |
[PropertyCategory(typeof(TestTag.Dates))] | |
[PropertyCategory(typeof(TestTag.Custom1))] | |
[PropertyCategory(typeof(TestTag.Custom2))] | |
public DateTime CreatedAt { | |
get { | |
return mCreatedAt; | |
} | |
} | |
[PropertyCategory(typeof(TestTag.Dates))] | |
public DateTime ModifiedAt { | |
get { | |
return mModifiedAt; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment