Swift Enum with multiple types - swift

I am trying to figure out how to duplicate my Java Enum into Swift and i don't know if
this is the right way.
My Enum in Java which i am trying to write in Swift:
public enum EnumDB {
DATABASE_NAME("DataBase"),
DATABASE_VERSION(1);
private String name;
private int value;
private EnumDB(String name) {
this.name = name;
}
private EnumDB(int value) {
this.value = value;
}
public String getName() {
return name;
}
public int getValue() {
return value;
}
}
My Swift Code:
enum EnumDB {
case Name,Version
func getName() -> String{
switch self{
case .Name: return "DataBase"
}
}
func getNumber() -> Int{
switch self{
case .Version: return 1
default: return 0
}
}
}
My questions are:
Is this the right way to create an Enum with multiple value types , each enum contains
a different type?
unfortunately this way i can call the methods getName() and getNumber() on each Enum which is bad because i would want those methods to be presented according to the enum type.
Enum Associative values and Raw Values didn't help
to conclusion what i am looking for is writing an enum that his values can contains different types.
thanks

You can definitely have an enum with associated values of different types, which I think can give you what you're looking for. This is how I might implement your example:
enum EnumDB {
case Name(String)
case Version(Int)
}
let namedDB = EnumDB.Name("databaseName")
switch namedDB {
case .Name(let name):
println("Database name is \(name)")
case .Version(let versionNumber):
println("Database version is \(versionNumber)")
}

Related

Swift associated types vs generic interface

I started learning swift and just learned about associated types and opaque types.
Take a look at the following example -
protocol Appendable {
associatedtype Item
var collection: [Item] { get set }
func Append(_ item: Item)
}
For which an implementation would be -
struct IntArray: Appendable {
typealias Item = Int
var collection: [Int] = []
func append(_ item: Int) {
collection.append(item)
}
}
I understand that any class that conforms to Appendable could declare it’s own type for Item and use that type, thus making the Appendable protocol more generic.
My question is, if and how is this any different from a generic interface in, let’s say, C#? (I come from a C# background). Also, if it is different, is there any reason that they chose to implement generic protocols that specific way?
Like so -
public interface IAppendable<Item> {
List<Item> Collection { get; }
void Append(Item item);
}
For which an implementation would look like this -
public class IntList: IAppendable<int> {
private List<int> _list = new List<int>();
public List<int> Collection => _list;
public void Append(int item) {
_list.Add(item);
}
}

Pass enum case as parameter in swift 4

So I´m trying to build a framework with a function like this
public func logScreen(screen: SomeEnum){
print(screen.rawValue)
}
and i want to pass as parameter a case of a string enum that is defined in the project that will make use of this framework
I don't think you can do this directly. But using swift protocol, you can achieve your goal I believe. You may review my idea.
First, you need to define a protocol in your framework. Say in you Framework class.
public protocol SomeEnum {
var rawValue: String { get }
}
Inside your framework class, you define your code:
public func logScreen(screen: SomeEnum){
print(screen.rawValue)
}
Now in your project, you can declare the enum and inherite the framework
protocol. Say for example in your project:
public enum MyEnum: SomeEnum {
case test
case debug
public var rawValue: String {
switch self {
case .test:
return "test"
case .debug:
return "Debug"
}
}
}
Now use the method from your project like below:
yourframeworkclass.logScreen(screen: MyEnum.test)

How to use AutoMapper to map an Enum Id to a queryable projection based on Enum Values?

I am trying to map an Enum value (Int16) to an IQueryable projection so that the string representation of the Enum value is used rather than the integer value for the database sorting.
The approach I used was taken from here.
Enum as follows:
public enum SafetyCategoryEnum : Int16 { High, Medium, Low }
See my AutoMapper mapping below:
config.CreateMap<SupplierContractEntity, SupplierContractEntityWrapper>()
.ForMember(dest => dest.SafetyCategoryEnumId,
opt => { opt.MapFrom(EnumerableExpressionHelper.CreateEnumToStringExpression((SupplierContractEntity e) => e.SafetyCategoryEnumId)); })
SupplierContractEntity is the EntityFramework Entity.
public class SupplierContractEntity : Entity
{
//Other properties removed for brevity
public Int16 SafetyCategoryEnumId { get; set; }
}
SupplierContractEntityWrapper is a custom business object:
public class SupplierContractEntityWrapper : EntityWrapper
{
//Other properties removed for brevity
public SafetyCategoryEnum? SafetyCategoryEnumId { get; set; }
}
Expression mapping is reversed in AutoMapper which is why the Entity maps to the business object
Implementation of CreateEnumToStringExpression:
public static class EnumerableExpressionHelper
{
public static Expression<Func<TSource, string>> CreateEnumToStringExpression<TSource, TMember>(Expression<Func<TSource, TMember>> memberAccess, string defaultValue = "")
{
var type = typeof(SafetyCategoryEnum);
var enumNames = Enum.GetNames(type);
var enumValues = (Int16[])Enum.GetValues(type);
var inner = (Expression)Expression.Constant(defaultValue);
var parameter = memberAccess.Parameters[0];
for (int i = 0; i < enumValues.Length; i++)
{
inner = Expression.Condition(
Expression.Equal(memberAccess.Body, Expression.Constant(enumValues[i])),
Expression.Constant(enumNames[i]), inner);
}
MyExpressionVisitor myExpressionVisitor = new MyExpressionVisitor();
var expression = Expression.Lambda<Func<TSource, string>>(inner, parameter);
myExpressionVisitor.Visit(expression);
return expression;
}
}
When performing a sort AutoMapper throws the following exception:
InvalidOperationException: Rewriting child expression from type 'System.Nullable`1[SafetyCategoryEnum]' to type 'System.String' is not allowed, because it would change the meaning of the operation.
If this is intentional, override 'VisitUnary' and change it to allow this rewrite.
Is there any way around this type issue?
Any help would be greatly appreciated!
This works for me with the latest AM, but you need to make the destination a string. I think you're not on the latest version and you've hit an already fixed bug.

Wicket - DropDownChoice from Enum to Primitive

Im having some problem with DropDownChoice.
I have an Enum with a list of school title like:
public enum StudyTitle {
NONE(null,null),ELEMENTARY("1","Elementary"),COLLEGE("2","College");
private String code;
private String description;
private StudyTitle(String code, String description){
setCode(code);
setDescription(description);
}
[setter and getter]
}
Then I have a Pojo with a String proprerty call "studyTitleCode" where I want to put the code (ex 1 for elementary, 2 for college etc...).
When I create a DropDownChoice Wicket doesn't allow me to have a proprerty Model of type String if the DropDownChoice is of type StudyTitle.
Ex.
[building the listOfStudyTitle as ArrayList of Enums]
DropDownChoice<String> studyLevel = new DropDownChoice<String>("id",new PropertyModel<String>(myPojo,"studyTitleCode"),listOfStudyTitle,new ChoiceRenderer<StudyTitle>("description","code"));
Is there a Method to allow Wicket to link one property of the Enum to the Property of Model?
Thanks
The choice options for an AbstractSingleSelectChoice must match the type of the value model. The only related config option for the DropDownChoice that I'm aware of is the IChoiceRenderer which allows you to set how the enum value is rendered (vs the default call toString()).
One option would be, instead of using the enum instance itself for your choices model, give the enum a String property that can be used:
public enum TestEnum {
ONE ("ONE"),
TWO ("TWO"),
THREE ("THREE");
private String value;
TestEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static List<String> getStringValues()
{
List<String> stringValues = new ArrayList<String>();
for (TestEnum test : values()) {
stringValues.add(test.getValue());
}
return stringValues;
}
}
#Override
protected void onInitialize() {
super.onInitialize();
IModel<String> myStringValueModel = new Model<String>();
add(new DropDownChoice<String>("id", myStringValueModel, TestEnum.getStringValues()));
}

How to store a complex type with only one value in Entity Framework?

I'm using EF Code First and have an entity which has a Telephone property of type PhoneNumber. The PhoneNumber class has some validation and convenience methods, but essentially holds a string with a correct phone number.
I want to persist this to the database as a simple string. How would I go about this?
Do I need to register some sort of type converter, or do I really need to expose a public property on my PhoneNumber class which is used as complex type (I'd rather not have a public property like this, since I would like PhoneNumber to be immutable).
This is my PhoneNumber class:
public class PhoneNumber {
private string _number;
public PhoneNumber(string number) {
if (!IsValid(number)) {
throw new ArgumentException("Invalid Dutch phone number.");
}
_number = number;
}
private static string Sanitize(string number) {
return number.Trim()
.Replace("-", String.Empty)
.Replace(" ", String.Empty);
}
public bool IsValid() {
return IsValid(this);
}
public static bool IsValid(string number) {
if (number == null) {
return false;
}
var cleanNumber = Sanitize(number);
return Regex.IsMatch(cleanNumber, #"^06\d{8}$");
}
public static implicit operator PhoneNumber(string number) {
return new PhoneNumber(number);
}
public static implicit operator string(PhoneNumber number) {
return number.ToString();
}
}
You will have to add this to your code:
public string Number
{
get { return _number; }
private set { _number = value; }
}
private PhoneNumber() {}
and map your class as complex type:
modelBuilder.ComplexType<PhoneNumber>();