What is the F# equivalent of this C# code? - f#

I used VB.Net when I started in C# there was a code translating site. It would be good to have this for F#
I wrote this C# code
public interface IData : INotifyPropertyChanged
{
Guid ID { get; set; }
}
public interface IVertex : INotifyPropertyChanged
{
}
public abstract class Vertex<IData>
{
public IData Properties { get; set; }
public Vertex() { }
public Vertex(IData Properties)
{
this.Properties = Properties ;
}
public string Tipo { get { return typeof(IData).Name; } }
}
public class Data_Person : IData
{
public event PropertyChangedEventHandler PropertyChanged;
public Guid ID { get; set; } = Guid.NewGuid();
public decimal Balance { get; set; }
public string Name { get; set; }
}
public class Person : Vertex<Data_Person>, IVertex
{
public Person()
{
this.Properties = new Data_Person();
}
public Person(Data_Person Properties) : base(Properties)
{ }
public event PropertyChangedEventHandler PropertyChanged;
}
public class EdgeLink<ISourceVertex, IEdgeData, ITargetVertex>
{
public EdgeLink()
{ }
public EdgeLink(ISourceVertex In, IEdgeData Edge, ITargetVertex Out)
{
this.In = In;
this.Properties = Edge;
this.Out = Out;
}
public ISourceVertex In { get; set; }
public IEdgeData Properties { get; set; }
public ITargetVertex Out { get; set; }
//public LoadStatus LoadStatus { get; set; } = LoadStatus.Uknown;
}
I am trying to do the same, but in F#.
How to 'translate' this to F# ?
I tried to translate, but it got messed, so far I have
type IData =
inherit INotifyPropertyChanged
abstract member ID: Guid with get, set
type IEdgeData =
inherit IData
type IVertex =
inherit INotifyPropertyChanged
type ISourceVertex =
inherit IVertex
type ITargetVertex =
interface
inherit IVertex
end

Since the comments indicate that you're having trouble with the event and the generic type, here's how you would convert those, specifically:
open System
open System.ComponentModel
type IData =
inherit INotifyPropertyChanged
abstract member ID: Guid
type IVertex = inherit INotifyPropertyChanged
[<AbstractClass>]
type Vertex<'data when 'data :> IData> (properties: 'data) =
member __.Properties = properties
member __.Tipo = typeof<'data>.Name
type DataPerson (id, balance, name) =
let propertyChanged = Event<_,_>()
member __.ID = id
member __.Balance = balance
member __.Name = name
interface IData with
member __.ID = id
[<CLIEvent>]
member __.PropertyChanged = propertyChanged.Publish
You just need a generic type variable 'data constrained to be an IData for the Vertex class and an F# Event<_,_> with a [] property for the PropertyChanged event.
Note, I left out the setters on the properties here. You can easily add them back if you really need them.
EDIT
Adding the person class:
type Person (person) =
inherit Vertex<DataPerson>(person)
let propertyChanged = Event<_,_>()
interface IVertex with
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
EDIT 2
Adding optional parameters in constructors (I also made the Vertex.Properties property mutable this time, since it wouldn't make much sense to keep it immutable if you could instantiate the class with it uninitialized). I probably wouldn't do it this way in a pure-F# solution, but this is a more direct representation of the original C# code:
[<AbstractClass>]
type Vertex<'data when 'data :> IData> (?properties: 'data) =
let vertexProperties = defaultArg properties Unchecked.defaultof<'data>
member val Properties = vertexProperties with get,set
member __.Tipo = typeof<'data>.Name
type DataPerson (id, balance, name) =
let propertyChanged = Event<_,_>()
member __.ID = id
member __.Balance = balance
member __.Name = name
interface IData with
member __.ID = id
[<CLIEvent>]
member __.PropertyChanged = propertyChanged.Publish
type Person (?person) =
inherit Vertex<DataPerson>(defaultArg person Unchecked.defaultof<DataPerson>)
let propertyChanged = Event<_,_>()
interface IVertex with
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish

Related

Unmapped properties: _entityWrapper

Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
AutoMapper created this type map for you, but your types cannot be mapped using the current configuration.
CustomerDto -> Customer_F18BD0407D7AB3084DFC14364CBC838E797CB114E45768DA5EB22B4A1CC94C26 (Destination member list)
WebApiCollection.DTO.CustomerDto -> System.Data.Entity.DynamicProxies.Customer_F18BD0407D7AB3084DFC14364CBC838E797CB114E45768DA5EB22B4A1CC94C26 (Destination member list)
Unmapped properties:
_entityWrapper
var customerInDb = _dbContext.Customers.SingleOrDefault(p => p.Id == customerDto.Id);
if (customerInDb == null)
return NotFound();
customerInDb = Mapper.Map(customerDto, customerInDb);
Have you tried?
customerInDb = Mapper.Map<Customer>(customerDto);
This can occur when the fields between the Dto and the Entity class don't line up. For example. My Dto contains two fields
public class ReworkDto: FullAuditEntity
{
public string WorkOrderNumber { get; set; }
public string WorkOrderBarcode { get; set; }
}
Those two fields are also in the entity class but the entity class also includes a navigation property (ReworkDetails)
[Table("Quality_Rework")]
public class QualityRework : FullAuditEntity
{
[Required, Column(Order = 8)]
public virtual string WorkOrderNumber { get; set; }
[Required, Column(Order = 9)]
public virtual string WorkOrderBarcode { get; set; }
public virtual ICollection<QualityReworkDetail> ReworkDetails { get; set; }
}
The particular error for this post would surface if I tried updating, using the following code
private void Update(ReworkDto entityDto)
{
try
{
var entityToUpdate = DbContext.QualityRework.FirstOrDefault(x => x.Id == entityDto.Id);
var updateRework = _autoMapper.Map(entityDto, entityToUpdate);
}
catch (Exception exc)
{
Console.WriteLine(exc);
throw;
}
}
To avoid getting the error I would need to CreateMap (AutoMapperModule.cs), instructing AutoMapper that when mapping between Dto -> Entity to Ignore() the ReworkDetails field.
CreateMap<domain.DTO.Quality.ReworkDto, infrastructure.Entities.Quality.QualityRework>()
.ForMember(dest => dest.ReworkDetails, opt => opt.Ignore());

Error: c# member names cannot be the same as their enclosing type

this is XML
<TEST ID=1 TITLE="HELLO" TEST=false/>
this file is XmlSerializer
[Serializable]
[XxmlRoot(ElementName = "TEST"]
public class TEST
{
[XmlAttribute(AttributeName = "ID"]
public int ID {get;set;}
[XmlAttribute(AttributeName = "TITLE"]
public string TITLE {get;set;}
[XmlAttribute(AttributeName = "TEST"]
public bool TEST {get;set;}
}
Run This Project
Error Message
"'TEST' member names cannot be the same as their enclosing type"
I understand it. but I CAN NOT rename this AttributeName and RootName,
XML file is Never Change, Not my File. How can I Change this Serializable File ?
You can rename your member variables while keeping the actual XML tags the same. The AttributeName you have used enables this. You can actually do this:
[Serializable]
[XmlRoot(ElementName = "TEST"]
public class TestTag
{
[XmlAttribute(AttributeName = "ID"]
public int IdAttribute { get; set; }
[XmlAttribute(AttributeName = "TITLE"]
public string TitleAttribute { get; set; }
[XmlAttribute(AttributeName = "TEST"]
public bool TestAttribute { get; set; }
}
or something similar. Your XML file will remain the same!

Serializing entity to XML - add method

Can anybody help me with the below?
Models
public class Integer
{
public int IntegerID { get; set; }
[Required(ErrorMessage = "Enter an integer")]
[Integer(ErrorMessage = "Enter an integer")]
public int IntegerValue { get; set; }
public int IntegerListID { get; set; }
public virtual IntegerList IntegerList { get; set; }
}
public class IntegerList
{
public int IntegerListID { get; set; }
public string Direction { get; set; }
public long Performance { get; set; }
public virtual ICollection<Integer> Integers { get; set; }
public IntegerList()
{
Integers = new List<Integer>();
}
}
Controller Action
public ActionResult XMLexport () {
Object obj = db.IntegerLists.Include("Integers");
Serialize(obj);
return View();
}
public static string Serialize(Object obj)
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
MemoryStream memoryStream = new MemoryStream();
serializer.WriteObject(memoryStream, obj);
return Encoding.UTF8.GetString(memoryStream.GetBuffer());
}
At the line
serializer.WriteObject(memoryStream, obj);
I'm getting the error:
Type 'System.Data.Entity.Infrastructure.DbQuery`1[[IntegerSorter.Models.IntegerList, IntegerSorter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' is an invalid collection type since it does not have a valid Add method with parameter of type 'IntegerSorter.Models.IntegerList'.
Can somebody advise me where and how to implement the Add method?
Update:
Changing:
Object obj = db.IntegerLists.Include("Integers");
to
Object obj = db.IntegerLists.Include("Integers").ToList();
results in:
Type 'System.Data.Entity.DynamicProxies.IntegerList_62F0932A6DFC38A25629DF18911498D42B3785A93BCE8B8D2F77C3363B3F4200' with data contract name 'IntegerList_62F0932A6DFC38A25629DF18911498D42B3785A93BCE8B8D2F77C3363B3F4200:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
Try changing this line:
Object obj = db.IntegerLists.Include("Integers");
To this:
Object obj = db.IntegerLists.Include("Integers").ToList();
This will cause the database query to run and give you a List<IntegerList> instead of a DbQuery<IntegerList>. This should then provide what the serializer wants (because it has a Add(IntegerList) method available as requested by the error).
I've accepted Greg's answer but feel I should detail the subsequent issues I had to work through:
Type 'System.Data.Entity.DynamicProxies.IntegerList_62F0932A6DFC38A25629DF18911498D42B3785A93BCE8B8D2F77C3363B3F4200' with data contract name 'IntegerList_62F0932A6DFC38A25629DF18911498D42B3785A93BCE8B8D2F77C3363B3F4200:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
was solved with:
Context.Configuration.ProxyCreationEnabled = false;
and then:
Object graph for type 'System.Collections.Generic.List`1[[IntegerSorter.Models.Integer, IntegerSorter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' contains cycles and cannot be serialized if reference tracking is disabled.
was solved by decorating the navigation property on the Integer class as below:
[IgnoreDataMember]
public virtual IntegerList IntegerList { get; set; }

Only parameterless constructors and initializers are supported in LINQ to Entities?

I have a ProductViewModel that converts a DTO (Product) at runtime.
public class ProductViewModel : IViewModel {
public ProductViewModel() {
Categories = new List<CategoryViewModel>();
}
#region DTO Helpers
public ProductViewModel(Product p) {
this.ID = p.ID;
this.Name = p.Name;
this.Price = p.Price;
Categories = new List<CategoryViewModel>();
}
#endregion
public int ID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public IEnumerable<CategoryViewModel> Categories { get; set; }
}
I've used this code with LINQ2SQL before and it's worked, but now with entity framework it doesn't:
var products = (from p in db.GetAll()
select new ProductViewModel(p));
I get this error:
Only parameterless constructors and initializers are supported in LINQ to Entities
Can anybody help explain/fix this?
var products = (from p in db.GetAll()
select new ProductViewModel{
ID = p.Id,
....
});
To retrieve all details from single entity use this
Context.Set<your entity>().AsQueryable();

Data validation with custom attributes (AttributeTargets.Class) on EF buddy classes

I have an Entity Framework generated class with the following properties:
public DateTime LaunchDate;
public DateTime ExpirationDate;
I need to enforce that ExpirationDate > LaunchDate.
I am using a buddy class as described in various posts.
I am applying custom validation attributes (on properties) to other properties in the same buddy class and these are working.
Since I need to compare two properties I am using an attribute directly on the class (AttributeTargets.Class)
Here is my custom validation attribute:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class PropertyMustBeGreaterThanAttribute : ValidationAttribute
{
private const string _defaultErrorMessage = "'{0}' must be greater than '{1}'!";
public PropertyMustBeGreaterThanAttribute(string property, string greaterThan)
: base(_defaultErrorMessage)
{
GreaterThan = greaterThan;
Property = property;
}
public string Property { get; private set; }
public string GreaterThan { get; private set; }
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
GreaterThan, Property);
}
public override bool IsValid(object value)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
IComparable greaterThan = properties.Find(GreaterThan, true /* ignoreCase */).GetValue(value) as IComparable;
IComparable property = properties.Find(Property, true /* ignoreCase */).GetValue(value) as IComparable;
return greaterThan.CompareTo(property) > 0;
}
}
First I am unsure to which class I need to apply the attribute to:
[MetadataType(typeof(PromotionValidation))]
[PropertyMustBeGreaterThanAttribute("RetailPrice")] // apply it here
public partial class Promotion
{
[PropertyMustBeGreaterThanAttribute("ExpirationDate", "LaunchDate")] // or here ???
public class PromotionValidation
{
Second, it's not working and I have no clue why!!!
I've tried adding attribute to both classes. Breakpoints in the constructor are hit (PropertyMustBeGreaterThanAttribute ), but IsValid is never called.
Pulling my hair out already....
Thanks!
Got it to work by implementing TypeID.
I assigned the attribute to the partial class:
[MetadataType(typeof(PromotionValidation))]
[PropertyMustBeGreaterThanAttribute("RetailPrice", "DiscountedPrice")]
[PropertyMustBeGreaterThanAttribute("ExpirationDate", "LaunchDate")]
[PropertyMustBeGreaterThanAttribute("ClaimDeadline", "ExpirationDate")]
public partial class Promotion
{
...
Here is the listing in case anyone needs it:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class PropertyMustBeGreaterThanAttribute : ValidationAttribute
{
private const string _defaultErrorMessage = "'{1}' must be greater than '{0}'!";
private readonly object _typeId = new object();
public PropertyMustBeGreaterThanAttribute(string property, string greaterThan)
: base(_defaultErrorMessage)
{
GreaterThan = greaterThan;
Property = property;
}
public string Property { get; private set; }
public string GreaterThan { get; private set; }
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
GreaterThan, Property);
}
public override bool IsValid(object value)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
IComparable greaterThan = properties.Find(GreaterThan, true /* ignoreCase */).GetValue(value) as IComparable;
IComparable property = properties.Find(Property, true /* ignoreCase */).GetValue(value) as IComparable;
return greaterThan.CompareTo(property) > 0;
}
public override object TypeId
{
get
{
return _typeId;
}
}
}

Resources