Non-ASCII characters in C # identifiers. NHibernate Link

I tried to enter non-ASCII characters in C # identifiers, and the program compiles and works just fine (at least at first glance). To be more precise, I use Croatian diacritics (čćđšž) in transfers. I really need to use these special characters, because I list enumerations of strings as value objects in NHibernate. It would be very ugly to avoid these standard characters, showing them as search queries to the user. Before I start using enums in this way on a large scale, I really need to know if there are any consequences (hidden traps) for such programming (especially with respect to NHibernate)? Or, if you have a better way to handle this, let me know.

In addition, are there any problems with the tools used for refactoring, SVN, etc.

+5
source share
4 answers

The C # language uses Unicode encoding, which means that your special character will not be a problem. However, I like to save the code in English without special characters. I have yet to find a problem that justifies the use of names related to culture.

From the C # language specification:

# , (§9.1). file - Unicode . , . , UTF-8.

2.1 ( Microsoft #)

+6

enum int NHibernate. int. "NullSafeGet", enum. , , . : . . "SpecialConversion" enum .

public class EnumToSpecialStringType<TEnum> : IUserType
{
    #region IUserType Members

    /// <summary>
    /// Reconstruct an object from the cacheable representation. At the very least this
    /// method should perform a deep copy if the type is mutable. (optional operation)
    /// </summary>
    /// <param name="cached">the object to be cached</param>
    /// <param name="owner">the owner of the cached object</param>
    /// <returns>a reconstructed object from the cachable representation</returns>
    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    /// <summary>
    /// Return a deep copy of the persistent state, stopping at entities and at collections.
    /// </summary>
    /// <param name="value">generally a collection element or entity field</param>
    /// <returns>a copy</returns>
    public object DeepCopy(object value)
    {
        return value;
    }

    /// <summary>
    /// Transform the object into its cacheable representation. At the very least this
    /// method should perform a deep copy if the type is mutable. That may not be enough
    /// for some implementations, however; for example, associations must be cached as
    /// identifier values. (optional operation)
    /// </summary>
    /// <param name="value">the object to be cached</param>
    /// <returns>a cacheable representation of the object</returns>
    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    /// <summary>
    /// Compare two instances of the class mapped by this type for persistent "equality"
    /// ie. equality of persistent state
    /// </summary>
    /// <param name="x"/>
    /// <param name="y"/>
    /// <returns/>
    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        return x.Equals(y);
    }

    /// <summary>
    /// Get a hashcode for the instance, consistent with persistence "equality"
    /// </summary>
    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

    /// <summary>
    /// Are objects of this type mutable?
    /// </summary>
    public bool IsMutable
    {
        get { return false; }
    }

    /// <summary>
    /// Retrieve an instance of the mapped class from a ADO.NET resultset.
    /// Implementors should handle possibility of null values.
    /// </summary>
    /// <param name="rs">a IDataReader</param>
    /// <param name="names">column names</param>
    /// <param name="owner">the containing entity</param>
    /// <returns/>
    /// <exception cref="HibernateException">HibernateException</exception>
    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var value = NHibernateUtil.String.NullSafeGet(rs, names[0]) as string;

        // Put you special conversion here (string -> enum)
        var converted = SpecialConversion(value);

        return converted;
    }

    /// <summary>
    /// Write an instance of the mapped class to a prepared statement.
    /// Implementors should handle possibility of null values.
    /// A multi-column type should be written to parameters starting from index.
    /// </summary>
    /// <param name="cmd">a IDbCommand</param>
    /// <param name="value">the object to write</param>
    /// <param name="index">command parameter index</param>
    /// <exception cref="HibernateException">HibernateException</exception>
    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var parameter = (IDataParameter)cmd.Parameters[index];

        // Do conversion from your enum to database string value
        var converted = SpecialConversion(value);

        parameter.Value = converted;
    }

    /// <summary>
    /// During merge, replace the existing (<paramref name="target"/>) value in the entity
    /// we are merging to with a new (<paramref name="original"/>) value from the detached
    /// entity we are merging. For immutable objects, or null values, it is safe to simply
    /// return the first parameter. For mutable objects, it is safe to return a copy of the
    /// first parameter. For objects with component values, it might make sense to
    /// recursively replace component values.
    /// </summary>
    /// <param name="original">the value from the detached entity being merged</param>
    /// <param name="target">the value in the managed entity</param>
    /// <param name="owner">the managed entity</param>
    /// <returns>the value to be merged</returns>
    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    /// <summary>
    /// The type returned by <c>NullSafeGet()</c>
    /// </summary>
    public Type ReturnedType
    {
        get
        {
            return typeof(TEnum);
        }
    }

    /// <summary>
    /// The SQL types for the columns mapped by this type. 
    /// </summary>
    public SqlType[] SqlTypes
    {
        get
        {
            return new[] { new SqlType(DbType.String) };
        }
    }

    #endregion
}

NHibernate, user :

Map(x => x.PropertyName, "ColumnName").CustomType<EnumToSpecialStringType<EnumType>>();

: , xml:

nHibernate

+3

, , .

, , ASCII:

public enum MyEnum
{
    NonAsciiName1,
    NonAsciiName2,
    NonAsciiName3,
}

, , ASCII:

public enum MyEnum
{
    AsciiName1,
    AsciiName2,
    AsciiName3,
}

public static class MyEnumExtensions
{
    static readonly Dictionary<MyEnum, string> map = new Dictionary<MyEnum, string>
    {
        { MyEnum.AsciiName1, "NonAsciiName1" },
        { MyEnum.AsciiName2, "NonAsciiName2" },
        { MyEnum.AsciiName3, "NonAsciiName3" },
    };

    public static string GetValue(this MyEnum key)
    {
        return map[key];
    }
}

:

// you probably had something like:
var myEnumValue = MyEnum.NonAsciiName1;
var value = myEnumValue.ToString();

// now becomes:
var myEnumValue = MyEnum.AsciiName1;
var value = myEnumValue.GetValue();

DEHAAS , . , , .

using System.ComponentModel;

public enum MyEnum
{
    [DescriptionAttribute("NonAsciiName1")] AsciiName1,
    [DescriptionAttribute("NonAsciiName2")] AsciiName2,
    [DescriptionAttribute("NonAsciiName3")] AsciiName3,
}

public static class MyEnumExtensions
{
    public static string GetValue(this MyEnum key)
    {
        return typeof(MyEnum).GetField(key.ToString())
                             .GetCustomAttributes(typeof(DescriptionAttribute), false)
                             .Cast<DescriptionAttribute>()
                             .Single()
                             .Description;
    }
}
+1

, , .

() . , .

Not a very oriented object, you may have a class in the code, which is a direct mapping between your listing and the value of the corresponding language, for example, in the form of nhibernate, for example:

<class name="DropDown" table="DropDown_Language">
    <!-- map onto the ENUMeration -->
    <id name="UniqueID" column="Id" type="Int32" >
        <generator class="identity" />
    </id>
    <property name="DropDownType" column="DropDownTypeId" type="DropDownType, Domain"/>
    <property name="Language" column="LanguageId" type="LanguageReferenceType,  "/>
    <property name="DropDownTypeDescription" column="DropDownTypeDescription" type="string"/>
</class>

In the DropDownTypeDescription column, you should put the values ​​of the drop-down list.

I hope I understand your question :-)

+1
source

All Articles