В качестве вариации решения yasimturks я определил одну функцию и несколько значений enum вместо пяти макросов.
Использование:
if (systemVersion(LessThan, @"5.0")) ...
.h файл:
typedef enum {
LessThan,
LessOrEqual,
Equal,
GreaterOrEqual,
GreaterThan,
NotEqual
} Comparison;
BOOL systemVersion(Comparison test, NSString* version);
.m файл:
BOOL systemVersion(Comparison test, NSString* version) {
NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare: version options: NSNumericSearch];
switch (test) {
case LessThan: return result == NSOrderedAscending;
case LessOrEqual: return result != NSOrderedDescending;
case Equal: return result == NSOrderedSame;
case GreaterOrEqual: return result != NSOrderedAscending;
case GreaterThan: return result == NSOrderedDescending;
case NotEqual: return result != NSOrderedSame;
}
}
Вы должны добавить префикс вашего приложения к именам, особенно к типу Comparison
.
Согласно просьбе вот подход с помощью CustomTypeDescriptor
для редактирования атрибутов во времени выполнения; примером здесь являются формы победы, но должно быть довольно просто подкачать его в WPF, чтобы видеть, работает ли это...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
// example POCO
class Foo {
static Foo()
{ // initializes the custom provider (the attribute-based approach doesn't allow
// access to the original provider)
TypeDescriptionProvider basic = TypeDescriptor.GetProvider(typeof(Foo));
FooTypeDescriptionProvider custom = new FooTypeDescriptionProvider(basic);
TypeDescriptor.AddProvider(custom, typeof(Foo));
}
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
// example form
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.Run( new Form {
Controls = {
new DataGridView {
Dock = DockStyle.Fill,
DataSource = new BindingList<Foo> {
new Foo { Name = "Fred", DateOfBirth = DateTime.Today.AddYears(-20) }
}
}
}
});
}
}
class FooTypeDescriptionProvider : TypeDescriptionProvider
{
ICustomTypeDescriptor descriptor;
public FooTypeDescriptionProvider(TypeDescriptionProvider parent) : base(parent) { }
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{ // swap regular descriptor for bespoke (Foo) descriptor
if (descriptor == null)
{
ICustomTypeDescriptor desc = base.GetTypeDescriptor(typeof(Foo), null);
descriptor = new FooTypeDescriptor(desc);
}
return descriptor;
}
}
class FooTypeDescriptor : CustomTypeDescriptor
{
internal FooTypeDescriptor(ICustomTypeDescriptor parent) : base(parent) { }
public override PropertyDescriptorCollection GetProperties()
{ // wrap the properties
return Wrap(base.GetProperties());
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{ // wrap the properties
return Wrap(base.GetProperties(attributes));
}
static PropertyDescriptorCollection Wrap(PropertyDescriptorCollection properties)
{
// here's where we have an opportunity to swap/add/remove properties
// at runtime; we'll swap them for pass-thru properties with
// edited atttibutes
List<PropertyDescriptor> list = new List<PropertyDescriptor>(properties.Count);
foreach (PropertyDescriptor prop in properties)
{
// add custom attributes here...
string displayName = prop.DisplayName;
if (string.IsNullOrEmpty(displayName)) displayName = prop.Name;
list.Add(new ChainedPropertyDescriptor(prop, new DisplayNameAttribute("Foo:" + displayName)));
}
return new PropertyDescriptorCollection(list.ToArray(), true);
}
}
class ChainedPropertyDescriptor : PropertyDescriptor
{
// this passes all requests through to the underlying (parent)
// descriptor, but has custom attributes etc;
// we could also override properties here...
private readonly PropertyDescriptor parent;
public ChainedPropertyDescriptor(PropertyDescriptor parent, params Attribute[] attributes)
: base(parent, attributes)
{
this.parent = parent;
}
public override bool ShouldSerializeValue(object component) { return parent.ShouldSerializeValue(component); }
public override void SetValue(object component, object value) { parent.SetValue(component, value); }
public override object GetValue(object component) { return parent.GetValue(component); }
public override void ResetValue(object component) { parent.ResetValue(component); }
public override Type PropertyType {get { return parent.PropertyType; } }
public override bool IsReadOnly { get { return parent.IsReadOnly; } }
public override bool CanResetValue(object component) {return parent.CanResetValue(component);}
public override Type ComponentType { get { return parent.ComponentType; } }
public override void AddValueChanged(object component, EventHandler handler) {parent.AddValueChanged(component, handler); }
public override void RemoveValueChanged(object component, EventHandler handler) { parent.RemoveValueChanged(component, handler); }
public override bool SupportsChangeEvents { get { return parent.SupportsChangeEvents; } }
}
Можно использовать в своих интересах новую функциональность Метаданных в Системе. ComponentModel. DataAnnotations, который позволит нам разделять MetaData от существующей модели предметной области.
, Например:
[MetadataType (typeof (BookingMetadata))]
public partial class Booking
{
// This is your custom partial class
}
public class BookingMetadata
{
[Required] [StringLength(15)]
public object ClientName { get; set; }
[Range(1, 20)]
public object NumberOfGuests { get; set; }
[Required] [DataType(DataType.Date)]
public object ArrivalDate { get; set; }
}
Можно хотеть рассмотреть использование шаблоны T4 охраны Damien для Linq К Sql. Изменение его шаблонов, скорее всего, дало бы Вам результаты, которые Вы ищете.
Hope это помогает!
Это - типичная проблема с генерацией кода; в то время как можно добавить участников и атрибуты уровня класса через дополнительный частичный класс, Вы не можете добавить атрибуты к сгенерированным участникам. Для компенсации некоторые основанные на атрибуте механизмы позволяют Вам определять атрибуты в классе (называющий участника), но не любой из тех Вы цитируете.
Одна жесткая опция состояла бы в том, чтобы записать TypeDescriptionProvider
, который предоставляет пользовательский PropertyDescriptor
определения для свойств. Это позволило бы Вам полностью управлять метаданными, используемыми UI обязательные инструменты как PropertyGrid
, DataGridView
, и т.д.
Однако это - возможно слишком много работы просто для установки некоторых UI propertiex, если можно также установить их вручную! Но если Вы интересуетесь преследованием той опции, сообщите мне - это - знакомая область мне, но слишком много кода для записи примера, если Вы не хотите его.
Примечание: если Вы используете PropertyGrid
, то Вы не можете устанавливать свойства вручную, но можно записать TypeConverter
, который является немного меньшим количеством работы, чем полное TypeDescriptionProvider
; просто наследуйтесь от ExpandableObjectConverter
и переопределите GetProperties()
. Вам все еще будет нужен контейнер PropertyDescriptor
, так все еще не тривиальный...
Можно использовать частичный класс, чтобы заставить объект реализовать интерфейс, который объявляет те же свойства объекта и затем помещает атрибуты на интерфейс.
Этот путь можно использовать интерфейсный тип для получения атрибутов от свойств.
я не знаю, будете ли Вы в состоянии использовать атрибуты этот путь, но можно попробовать что-то как этот.
Пример:
public interface IConcept {
long Code { get; set; }
[Unique]
string Name { get; set; }
bool IsDefault { get; set; }
}
public partial class Concept : IConcept { }
[Table(Name="dbo.Concepts")]
public partial class Concept
{
//...
}
Можно также писать/использовать другой генератор кода вместо MSLinqToSQLGenerator по умолчанию.
Одна опция начать с этот .
я создал свое собственное, согласно моим потребностям. Я не знаю, существует ли способ указать, какие атрибуты должны быть помещены в каждое свойство с помощью Разработчика DBML или xml файла, но возможно можно найти способ использовать эту альтернативу для помощи Вам с Вашей проблемой.