Bu herhangi bir zamanda veya gelecekte tel üzerinden (seri hale getirilmiş / seri hale getirilmiş) geçecek mi? Tek kimlik türünü who-know-how-how-full tam nesnesi üzerinde destekleyin.
Kimliğin varlığının güvenliğini sağlamak için arıyorsanız, o zaman da kod çözümleri var. Bir örneğe ihtiyacınız olursa haberim olsun.
Düzenleme: Kimlik tipinin güvenliği konusunda genişleyen:
Öyleyse, yöntemine bakalım:
public Foo GetItem(int id) {}
Yalnızca iletilen tamsayının bir nesne için olduğunu umuyoruz . Birisi onu kötüye kullanabilir ve bazı nesnelerin tamsayı kimliğini ya da sadece elle yazarak geçebilir . Güvenli değil . İkincisi, pass'ı bir nesne sürümü kullansanız bile , birinin değiştirebileceği bir kimlik alanına sahip olduğumdan eminim . Ve son olarak, eğer bunlar sadece bir dönüş tipi değiştiğinden bir sınıfta bunlar mevcutsa, metot aşırı yükünü kullanamazsınız. Bu yöntemi C # 'da type-safe bakmak için biraz yeniden yazalım:id
Foo
Bar
812341
Foo
Foo
Foo
int
public Foo GetItem(IntId<Foo> id) {}
Bu yüzden IntId
ona genel bir parçası olan bir sınıf tanıttım . Bu özel durumda, sadece int
bununla ilişkili olanı istiyorum Foo
. Sadece çıplak olarak geçemem int
ya IntId<Bar>
da yanlışlıkla ona bir şey atamam. Aşağıda bu tip güvenli tanımlayıcıları nasıl yazdım. Gerçek yatan manipülasyonu, germe notu mı int
olduğunu sadece veri erişim katmanında. Yukarıda sadece güçlü tipi gören ve iç int
kimliğine (doğrudan) erişimi olmayan herhangi bir şey . Bunun için bir sebep olmamalı.
IModelId.cs arayüzü:
namespace GenericIdentifiers
{
using System.Runtime.Serialization;
using System.ServiceModel;
/// <summary>
/// Defines an interface for an object's unique key in order to abstract out the underlying key
/// generation/maintenance mechanism.
/// </summary>
/// <typeparam name="T">The type the key is representing.</typeparam>
[ServiceContract]
public interface IModelId<T> where T : class
{
/// <summary>
/// Gets a string representation of the domain the model originated from.
/// </summary>
/// <value>The origin.</value>
[DataMember]
string Origin
{
[OperationContract]get;
}
/// <summary>
/// The model instance identifier for the model object that this <see cref="IModelId{T}"/> refers to.
/// Typically, this is a database key, file name, or some other unique identifier.
/// <typeparam name="TKeyDataType">The expected data type of the identifier.</typeparam>
/// </summary>
/// <typeparam name="TKeyDataType">The expected data type of the identifier.</typeparam>
/// <returns>The unique key as the data type specified.</returns>
[OperationContract]
TKeyDataType GetKey<TKeyDataType>();
/// <summary>
/// Performs an equality check on the two model identifiers and returns <c>true</c> if they are equal; otherwise
/// <c>false</c> is returned. All implementations must also override the equal operator.
/// </summary>
/// <param name="obj">The identifier to compare against.</param>
/// <returns><c>true</c> if the identifiers are equal; otherwise <c>false</c> is returned.</returns>
[OperationContract]
bool Equals(IModelId<T> obj);
}
}
ModelIdBase.cs ana sınıfı:
namespace GenericIdentifiers
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
/// <summary>
/// Represents an object's unique key in order to abstract out the underlying key generation/maintenance mechanism.
/// </summary>
/// <typeparam name="T">The type the key is representing.</typeparam>
[DataContract(IsReference = true)]
[KnownType("GetKnownTypes")]
public abstract class ModelIdBase<T> : IModelId<T> where T : class
{
/// <summary>
/// Gets a string representation of the domain the model originated from.
/// </summary>
[DataMember]
public string Origin
{
get;
internal set;
}
/// <summary>
/// The model instance identifier for the model object that this <see cref="ModelIdBase{T}"/> refers to.
/// Typically, this is a database key, file name, or some other unique identifier.
/// </summary>
/// <typeparam name="TKeyDataType">The expected data type of the identifier.</typeparam>
/// <returns>The unique key as the data type specified.</returns>
public abstract TKeyDataType GetKey<TKeyDataType>();
/// <summary>
/// Performs an equality check on the two model identifiers and returns <c>true</c> if they are equal;
/// otherwise <c>false</c> is returned. All implementations must also override the equal operator.
/// </summary>
/// <param name="obj">The identifier to compare against.</param>
/// <returns>
/// <c>true</c> if the identifiers are equal; otherwise <c>false</c> is returned.
/// </returns>
public abstract bool Equals(IModelId<T> obj);
protected static IEnumerable<Type> GetKnownTypes()
{
return new[] { typeof(IntId<T>), typeof(GuidId<T>) };
}
}
}
IntId.cs:
namespace GenericIdentifiers
{
// System namespaces
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
/// <summary>
/// Represents an abstraction of the database key for a Model Identifier.
/// </summary>
/// <typeparam name="T">The expected owner data type for this identifier.</typeparam>
[DebuggerDisplay("Origin={Origin}, Integer Identifier={Id}")]
[DataContract(IsReference = true)]
public sealed class IntId<T> : ModelIdBase<T> where T : class
{
/// <summary>
/// Gets or sets the unique ID.
/// </summary>
/// <value>The unique ID.</value>
[DataMember]
internal int Id
{
get;
set;
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="intIdentifier1">The first Model Identifier to compare.</param>
/// <param name="intIdentifier2">The second Model Identifier to compare.</param>
/// <returns>
/// <c>true</c> if the instances are equal; otherwise <c>false</c> is returned.
/// </returns>
public static bool operator ==(IntId<T> intIdentifier1, IntId<T> intIdentifier2)
{
return object.Equals(intIdentifier1, intIdentifier2);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="intIdentifier1">The first Model Identifier to compare.</param>
/// <param name="intIdentifier2">The second Model Identifier to compare.</param>
/// <returns>
/// <c>true</c> if the instances are equal; otherwise <c>false</c> is returned.
/// </returns>
public static bool operator !=(IntId<T> intIdentifier1, IntId<T> intIdentifier2)
{
return !object.Equals(intIdentifier1, intIdentifier2);
}
/// <summary>
/// Performs an implicit conversion from <see cref="IntId{T}"/> to <see cref="System.Int32"/>.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator int(IntId<T> id)
{
return id == null ? int.MinValue : id.GetKey<int>();
}
/// <summary>
/// Performs an implicit conversion from <see cref="System.Int32"/> to <see cref="IntId{T}"/>.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator IntId<T>(int id)
{
return new IntId<T> { Id = id };
}
/// <summary>
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current
/// <see cref="T:System.Object"/>.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current
/// <see cref="T:System.Object"/>.</param>
/// <returns>true if the specified <see cref="T:System.Object"/> is equal to the current
/// <see cref="T:System.Object"/>; otherwise, false.</returns>
/// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception>
public override bool Equals(object obj)
{
return this.Equals(obj as IModelId<T>);
}
/// <summary>
/// Serves as a hash function for a particular type.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
public override int GetHashCode()
{
unchecked
{
var hash = 17;
hash = (23 * hash) + (this.Origin == null ? 0 : this.Origin.GetHashCode());
return (31 * hash) + this.GetKey<int>().GetHashCode();
}
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Origin + ":" + this.GetKey<int>().ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Performs an equality check on the two model identifiers and returns <c>true</c> if they are equal;
/// otherwise <c>false</c> is returned. All implementations must also override the equal operator.
/// </summary>
/// <param name="obj">The identifier to compare against.</param>
/// <returns>
/// <c>true</c> if the identifiers are equal; otherwise <c>false</c> is returned.
/// </returns>
public override bool Equals(IModelId<T> obj)
{
if (obj == null)
{
return false;
}
return (obj.Origin == this.Origin) && (obj.GetKey<int>() == this.GetKey<int>());
}
/// <summary>
/// The model instance identifier for the model object that this <see cref="ModelIdBase{T}"/> refers to.
/// Typically, this is a database key, file name, or some other unique identifier.
/// </summary>
/// <typeparam name="TKeyDataType">The expected data type of the identifier.</typeparam>
/// <returns>The unique key as the data type specified.</returns>
public override TKeyDataType GetKey<TKeyDataType>()
{
return (TKeyDataType)Convert.ChangeType(this.Id, typeof(TKeyDataType), CultureInfo.InvariantCulture);
}
/// <summary>
/// Generates an object from its string representation.
/// </summary>
/// <param name="value">The value of the model's type.</param>
/// <returns>A new instance of this class as it's interface containing the value from the string.</returns>
internal static ModelIdBase<T> FromString(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
int id;
var originAndId = value.Split(new[] { ":" }, StringSplitOptions.None);
if (originAndId.Length != 2)
{
throw new ArgumentOutOfRangeException("value", "value must be in the format of Origin:Identifier");
}
return int.TryParse(originAndId[1], NumberStyles.None, CultureInfo.InvariantCulture, out id)
? new IntId<T> { Id = id, Origin = originAndId[0] }
: null;
}
}
}
ve, kod tabanımı tamamlama uğruna, bir tane de GUID varlıkları olan GuidId.cs:
namespace GenericIdentifiers
{
// System namespaces
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
/// <summary>
/// Represents an abstraction of the database key for a Model Identifier.
/// </summary>
/// <typeparam name="T">The expected owner data type for this identifier.</typeparam>
[DebuggerDisplay("Origin={Origin}, GUID={Id}")]
[DataContract(IsReference = true)]
public sealed class GuidId<T> : ModelIdBase<T> where T : class
{
/// <summary>
/// Gets or sets the unique ID.
/// </summary>
/// <value>The unique ID.</value>
[DataMember]
internal Guid Id
{
get;
set;
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="guidIdentifier1">The first Model Identifier to compare.</param>
/// <param name="guidIdentifier2">The second Model Identifier to compare.</param>
/// <returns>
/// <c>true</c> if the instances are equal; otherwise <c>false</c> is returned.
/// </returns>
public static bool operator ==(GuidId<T> guidIdentifier1, GuidId<T> guidIdentifier2)
{
return object.Equals(guidIdentifier1, guidIdentifier2);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="guidIdentifier1">The first Model Identifier to compare.</param>
/// <param name="guidIdentifier2">The second Model Identifier to compare.</param>
/// <returns>
/// <c>true</c> if the instances are equal; otherwise <c>false</c> is returned.
/// </returns>
public static bool operator !=(GuidId<T> guidIdentifier1, GuidId<T> guidIdentifier2)
{
return !object.Equals(guidIdentifier1, guidIdentifier2);
}
/// <summary>
/// Performs an implicit conversion from <see cref="GuidId{T}"/> to <see cref="System.Guid"/>.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Guid(GuidId<T> id)
{
return id == null ? Guid.Empty : id.GetKey<Guid>();
}
/// <summary>
/// Performs an implicit conversion from <see cref="System.Guid"/> to <see cref="GuidId{T}"/>.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator GuidId<T>(Guid id)
{
return new GuidId<T> { Id = id };
}
/// <summary>
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current
/// <see cref="T:System.Object"/>.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current
/// <see cref="T:System.Object"/>.</param>
/// <returns>true if the specified <see cref="T:System.Object"/> is equal to the current
/// <see cref="T:System.Object"/>; otherwise, false.</returns>
/// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception>
public override bool Equals(object obj)
{
return this.Equals(obj as IModelId<T>);
}
/// <summary>
/// Serves as a hash function for a particular type.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
public override int GetHashCode()
{
unchecked
{
var hash = 17;
hash = (23 * hash) + (this.Origin == null ? 0 : this.Origin.GetHashCode());
return (31 * hash) + this.GetKey<Guid>().GetHashCode();
}
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Origin + ":" + this.GetKey<Guid>();
}
/// <summary>
/// Performs an equality check on the two model identifiers and returns <c>true</c> if they are equal;
/// otherwise <c>false</c> is returned. All implementations must also override the equal operator.
/// </summary>
/// <param name="obj">The identifier to compare against.</param>
/// <returns>
/// <c>true</c> if the identifiers are equal; otherwise <c>false</c> is returned.
/// </returns>
public override bool Equals(IModelId<T> obj)
{
if (obj == null)
{
return false;
}
return (obj.Origin == this.Origin) && (obj.GetKey<Guid>() == this.GetKey<Guid>());
}
/// <summary>
/// The model instance identifier for the model object that this <see cref="ModelIdBase{T}"/> refers to.
/// Typically, this is a database key, file name, or some other unique identifier.
/// </summary>
/// <typeparam name="TKeyDataType">The expected data type of the identifier.</typeparam>
/// <returns>The unique key as the data type specified.</returns>
public override TKeyDataType GetKey<TKeyDataType>()
{
return (TKeyDataType)Convert.ChangeType(this.Id, typeof(TKeyDataType), CultureInfo.InvariantCulture);
}
/// <summary>
/// Generates an object from its string representation.
/// </summary>
/// <param name="value">The value of the model's type.</param>
/// <returns>A new instance of this class as it's interface containing the value from the string.</returns>
internal static ModelIdBase<T> FromString(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
Guid id;
var originAndId = value.Split(new[] { ":" }, StringSplitOptions.None);
if (originAndId.Length != 2)
{
throw new ArgumentOutOfRangeException("value", "value must be in the format of Origin:Identifier");
}
return Guid.TryParse(originAndId[1], out id) ? new GuidId<T> { Id = id, Origin = originAndId[0] } : null;
}
}
}